Wir haben mehr oder weniger Menüs mit zwei oder drei Ebenen erstellt, z. B. Baumverzeichnisse und Produktklassifizierungen. Wenn wir auf mehr Klassifizierungsebenen stoßen, verwenden wir im Allgemeinen die Rekursion. Die Verwendung von Rekursion in einem Programm erhöht mehr oder weniger den Leistungsaufwand.
Ich habe zuvor ASP.net verwendet, um ein nicht rekursives Klassifizierungsverzeichnis auf unendlicher Ebene im Programm zu implementieren, aber da die Portabilität nicht gut ist, habe ich es in eine gespeicherte Prozedur geändert und es für alle zum gemeinsamen Lernen verschickt. Während des Testvorgangs wurden keine Probleme festgestellt. Außerdem wurde der Code nicht optimiert.
Normalerweise dienen die meisten unserer Operationen dem Lesen von Verzeichnissen, daher benötigen wir in der folgenden Implementierung nur eine Select-Anweisung zum Lesen. Ohne Rekursion ist die Ebene theoretisch unendlich ~!
=============================================== ====================
Tabellenstruktur:
Tabellenname: Tb_Column
Tabellenstruktur (alle Felder sind nicht leer):
Column_ID int Primärschlüssel (Hinweis: kein Bezeichner)
Column_Name nvarchar(50) Klassifizierungsname
Parent_ID int Übergeordnete Kategorie-ID (Standardwert 0)
Column_Path nvarchar(1000) Klassifizierungspfad
Column_Depth int Klassifizierungstiefe (Standardwert 0)
Column_Order int sort (Standard 0)
Column_Intro nvarchar(1000) Klassifizierungsbeschreibung
========================================== === =================
Gespeicherte Prozedur eins: Erstellen Sie eine neue Klassifizierung.
CREATE PROCEDURE sp_Column_Insert
(
@Parent_ID int,
@Column_Name nvarchar(50),
@Column_Intro nvarchar(1000)
)
ALS
Deklarieren Sie @Err als int
Setze @Err=0
Beginn der Tran
– Rufen Sie die Spalten-ID aus vorhandenen Datensätzen ab
Deklarieren Sie @Column_ID als int
Deklarieren Sie @Column_Depth als int
Wählen Sie @Column_ID = Max(Column_ID) From Tb_Column
WENN @Column_ID nicht Null ist
Setzen Sie @Column_ID = @Column_ID+1
Anders
Setze @Column_ID = 1
– Bestimmen Sie, ob es sich um eine Spalte der obersten Ebene handelt, und legen Sie deren Column_Path und Column_Order fest
@Column_Path als nvarchar(1000) deklarieren
Deklarieren Sie @Column_Order als int
WENN @Parent_ID = 0
Beginnen
Setze @Column_Path =Ltrim(Str(@Column_ID))
Wählen Sie @Column_Order = Max(Column_Order) From Tb_Column
WENN @Column_Order nicht Null ist
Setzen Sie @Column_Order = @Column_Order + 1
Sonst – Wenn kein Datensatz gefunden wird, bedeutet dies, dass dies der erste Datensatz ist
Setzen Sie @Column_Order = 1
--Depth
Setzen Sie @Column_Depth = 1
Ende
Anders
Beginnen
--Ermitteln Sie den Pfad und die Tiefe des übergeordneten Knotens
Wählen Sie @Column_Path = Column_Path, @Column_Depth = Column_Depth From Tb_Column, wobei
Column_ID=@Parent_ID
WENN @Column_Path Null ist
Beginnen
Setzen Sie @Err = 1
Gehe zum Ende
Ende
– Rufen Sie die maximale Sequenznummer unter demselben übergeordneten Knoten ab
Wählen Sie @Column_Order = Max(Column_Order) From Tb_PicColumn, wobei Column_Path wie
''+@Column_Path+'|%' oder Column_ID = @Parent_ID ist
IF @Column_Order Is Not Null – Wenn die Sequenznummer vorhanden ist, addieren Sie 1 zu allen Sequenznummern nach der Sequenznummer
Beginnen
--Aktualisieren Sie die Sequenznummern aller Knoten nach dem aktuell einzufügenden Knoten
Tb_Column aktualisieren Set Column_Order = Column_Order +1 Wo Column_Order
>@Column_Order
--Die maximale Sequenznummer unter demselben übergeordneten Knoten plus 1 bildet eine eigene Sequenznummer
Setzen Sie @Column_Order = @Column_Order + 1
Ende
Anders
Beginnen
Setzen Sie @Err=1
Gehe zum Ende
Ende
– Der Pfad des übergeordneten Knotens plus seine eigene ID-Nummer bilden einen eigenen Pfad
Setze @Column_Path = @Column_Path + '|' + Ltrim(Str(@Column_ID))
--Depth
Setze @Column_Depth = @Column_Depth+1
End
Insert Into Tb_Column(Column_ID,Column_Name,Parent_ID,Column_Path,
Column_Depth,Column_Order,Column_Intro) Values(@Column_ID,@Column_Name,@Parent_ID,@Column_Path,@Column_Depth,@Column_Order ,@Column_Intro )
WENN @@Fehler<>0
Beginnen
Setzen Sie @Err=1
Gehe zum Ende
Ende
– Aktualisiert die REIHENFOLGE des Datensatzes nach dem aktuellen Datensatz
--Update Tb_Column Set Column_Order = Column_Order+1 Wo Column_Order > @Column_Order
theEnd:
WENN @Err=0
Beginnen
Trans. begehen
Geben Sie @Column_ID zurück
Ende
Anders
Beginnen
Rollback-Tran
Gibt 0 zurück
Ende
GEHEN
============================================== ============================
Gespeicherte Prozedur zwei: Kategorie löschen
PROZEDUR ERSTELLEN sp_Column_Delete
(
@Column_ID int
)
ALS
Deklarieren Sie @Err als int
Setzen Sie @Err = 0
Beginnen Sie mit der Transkription
- Überprüfen Sie zunächst, ob sich unter dem Knoten untergeordnete Knoten befinden
Wählen Sie Column_ID aus Tb_Column aus, wobei Parent_ID = @Column_ID ist
WENN @@RowCount<>0
Beginnen
Setzen Sie @Err = 1
Gehe zum Ende
Ende
– Ruft die Column_Order des Knotens ab, um die Reihenfolge anderer Datensätze nach dem Löschen zu ordnen
Deklarieren Sie @Column_Order als int
Wählen Sie @Column_Order = Column_Order From Tb_Column, wobei Column_ID = @Column_ID
WENN @Column_Order NULL ist
Beginnen
Setzen Sie @Err =2
Gehe zum Ende
Ende
– Aktualisiert die Column_Order anderer Datensätze
Tb_Column aktualisieren Set Column_Order = Column_Order -1 Wo Column_Order >@Column_Order
WENN @@Fehler<>0
Beginnen
Setzen Sie @Err =3
Gehe zum Ende
den --delete-
Vorgang
Aus Tb_Column löschen, wobei Column_ID=@Column_ID
WENN @@Fehler<>0
Beginnen
Setzen Sie @Err =4
Gehe zum Ende
Ende
– Aktualisieren Sie die Column_ID anderer Datensätze
--Update Tb_Column Set Column_ID= Column_ID - 1 Wo Column_ID >@Column_ID
--IF @@Error<>0
-- Beginnen
-- Setzen Sie @Err =5
– Gehe zum Ende
-- End
theEnd:
WENN @Err = 0
Beginnen
Trans. begehen
Rückgabe 0 – erfolgreich gelöscht
Ende
Anders
Beginnen
WENN @Err=1
Beginnen
Rollback-Tran
Rückgabe 1 – hat untergeordnete Knoten
Ende
Anders
Beginnen
Rollback-Tran
Rückgabe 2 – Unbekannter Fehler
Ende
Ende
GEHEN
=============================================== ================
Gespeicherte Prozedur drei: Klassifizierung bearbeiten
PROZEDUR ERSTELLEN sp_Column_Update
(
@Column_ID int,
@Parent_ID int,
@Column_Name nvarchar(50),
@Column_Intro nvarchar(1000)
)
ALS
Deklarieren Sie @Err als int
Setze @Err=0
Begin Tran
– Rufen Sie die Werte vor der Änderung ab: Parent_ID, Column_Depth, Column_Order
Deklarieren Sie @oParent_ID als int
Deklarieren Sie @oColumn_Depth als int
Deklarieren Sie @oColumn_Order als int
Deklarieren Sie @oColumn_Path als nvarchar(1000).
Wählen Sie @oParent_ID = Parent_ID, @oColumn_Depth = Column_Depth, @oColumn_Order = Column_Order, @oColumn_Path = Column_Path aus Tb_Column, wobei Column_ID = @Column_ID
WENN @oParent_ID Null ist
Beginnen
Setzen Sie @Err = 1
Gehe zum Ende
Ende
– Wenn sich die übergeordnete ID nicht geändert hat, ändern Sie direkt den Spaltennamen und die Spalteneinführung.
WENN @oParent_ID = @Parent_ID
Beginnen
Aktualisieren Sie Tb_Column. Legen Sie Column_Name = @Column_Name, Column_Intro = @Column_Intro fest, wobei Column_ID = @Column_ID
WENN @@Fehler <> 0
Setzen Sie @Err = 2
Gehe zum Ende
Ende
Deklarieren Sie @nColumn_Path als nvarchar(1000)
Deklarieren Sie @nColumn_Depth als int
Deklarieren Sie @nColumn_Order als int
– Ermitteln Sie die Anzahl der Knoten, die im aktuellen Knoten als übergeordnetem Knoten enthalten sind [einschließlich sich selbst]. Hinweis: Wenn „1“ zurückgegeben wird, bedeutet dies, dass es sich um einen einzelnen Knoten handelt
Deklarieren Sie @theCount als int
Wählen Sie @theCount = Count(Column_ID) From Tb_Column Where Column_ID=@Column_ID oder Column_Path wie ''+@oColumn_Path+'|%'
WENN @theCount Null ist
Beginnen
Setzen Sie @Err = 3
Gehe zum Ende
End
IF @Parent_ID=0 – Wenn es als Knoten der obersten Ebene festgelegt ist, legen Sie den Knoten auf den letzten Knoten der obersten Ebene fest
Beginnen
--Print 'Als Spalte der obersten Ebene festlegen'
Setze @nColumn_Path = Ltrim(Str(@Column_ID))
Setzen Sie @nColumn_Depth =1.
Wählen Sie @nColumn_Order = Max(Column_Order) aus Tb_Column
WENN @nColumn_Order NULL ist
Beginnen
Setzen Sie @Err = 4
Gehe zum Ende
End
Set @nColumn_Order = @nColumn_Order - @theCount + 1
--Update drei Teile 1 Der Knoten selbst 2 Alle untergeordneten Knoten 2 Die Reihenfolge der nachfolgenden Datensätze vor diesem Baum ändert sich
--Print 'Alle Spalten nach der vorherigen Position dieser Spalte aktualisieren [mit Ausnahme der Unterspalten unter dieser Spalte]: Column_Order'
Update Tb_Column Set Column_Order = Column_Order-@theCount Where (Column_Order >@oColumn_Order) And (Column_Path Not like ''+@oColumn_Path+'|%' )
WENN @@Fehler <> 0
Beginnen
Setzen Sie @Err = 7
Gehe zum Ende
End
--Print 'Diese Spalte aktualisieren: Parent_ID, Column_Path, Column_Depth, Column_Order, Column_Name, Column_Intro'
Drucken 'Order : '+Ltrim(Str(@nColumn_Order))
Tb_Column Set aktualisieren Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro Wo Column_ID = @Column_ID
WENN @@Fehler <> 0
Beginnen
Setzen Sie @Err = 5
Gehe zum Ende
End
--Print 'Alle Unterspalten unter dieser Spalte aktualisieren: Column_Path, Column_Depth, Column_Order'
Update Tb_Column Set Column_Path = Replacement(Column_Path,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth-@oColumn_Depth),Column_Order = Column_Order+( @nColumn_Order-@oColumn_Order) Wobei Column_Path wie. ''+@oColumn_Path +'|%'
WENN @@Fehler <> 0
Beginnen
Setzen Sie @Err = 6
Gehe zum Ende
Ende
Ende
Anders
Beginnen
--Rufen Sie die relevanten Informationen des zukünftigen übergeordneten Knotens ab und legen Sie die relevanten Werte dieses Knotens fest
Wählen Sie @nColumn_Depth = Column_Depth,@nColumn_Path = Column_Path From Tb_Column, wobei Column_ID = @Parent_ID
WENN @nColumn_Depth NULL ist oder @nColumn_Path Null ist
Beginnen
Setzen Sie @Err = 8
Gehe zum Ende
Ende
Setzen Sie @nColumn_Depth = @nColumn_Depth +1
Wählen Sie @nColumn_Order =Max(Column_Order) From Tb_Column Where Column_ID = @Parent_ID oder Column_Path wie ''+@nColumn_Path+'|%'
WENN @nColumn_Order NULL ist
Beginnen
Setzen Sie @Err = 9
Gehe zum Ende
End
Set @nColumn_Path = @nColumn_Path +'|'+ Ltrim(Str(@Column_ID))
IF @nColumn_Order = @oColumn_Order+1 --Wenn der neue übergeordnete Knoten der nächste Geschwisterknoten über der ursprünglichen Position ist, ändert sich die Reihenfolge aller Knoten anders sein
Beginnen
Tb_Column Set aktualisieren Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth, Column_Name = @Column_Name,Column_Intro = @Column_Intro Wo Column_ID = @Column_ID
WENN @@Fehler <> 0
Beginnen
Setzen Sie @Err = 10
Gehe zum Ende
Ende
End
Set @nColumn_Order = @nColumn_Order + 1
--Update drei Teile 1 Die Reihenfolge der folgenden (oder vorherigen) Datensätze, bevor sich dieser Baum ändert 1 Der Knoten selbst 3 Alle untergeordneten Knoten
--Unterteilt in Aufwärtsbewegung oder Abwärtsbewegung
--Print 'Alle Spalten nach der vorherigen Position dieser Spalte [oder der Position nach dieser Spalte] aktualisieren [ausgenommen Unterspalten unter dieser Spalte]: Column_Order'
WENN @nColumn_Order < @oColumn_Order
Beginnen
Tb_Column aktualisieren Set Column_Order = Column_Order+@theCount Where Column_Order<@oColumn_Order And Column_Order >=@nColumn_Order And (Column_Path Not like ''+@oColumn_Path+'|%' ) And Column_ID<>@Column_ID
WENN @@Fehler <> 0
Beginnen
Setzen Sie @Err = 12
Gehe zum Ende
Ende
Ende
Anders
Beginnen
Tb_Column aktualisieren Set Column_Order = Column_Order-@theCount Wo Column_Order >@oColumn_Order und Column_Order<@nColumn_Order und (Column_Path nicht wie ''+@oColumn_Path+'|%' ) und Column_ID<>@Column_ID
WENN @@Fehler <> 0
Beginnen
Setzen Sie @Err = 13
Gehe zum Ende
Ende
End
--Print 'Diese Spalte aktualisieren: Parent_ID, Column_Path, Column_Depth, Column_Order, Column_Name, Column_Intro'
Drucken 'Order : '+Ltrim(Str(@nColumn_Order))
WENN @nColumn_Order > @oColumn_Order
Setze @nColumn_Order = @nColumn_Order - @theCount
Tb_Column Set aktualisieren Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro Wo Column_ID = @Column_ID
WENN @@Fehler <> 0
Beginnen
Setzen Sie @Err = 10
Gehe zum Ende
End
--Print 'Alle Unterspalten unter dieser Spalte aktualisieren: Column_Paht, Column_Depth, Column_Order'
Update Tb_Column Set Column_Path = Replacement(Column_Path,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth-@oColumn_Depth),Column_Order = Column_Order+(@nColumn_Order-@oColumn_Order) Where Column_Path like . ''+@oColumn_Path+ '|%'
WENN @@Fehler <> 0
Beginnen
Setzen Sie @Err = 11
Gehe zum Ende
Ende
Schluss mit
dem Ende:
IF @Err<>0 – Wenn ein Fehler vorliegt, wird die Fehlernummer zurückgegeben
Beginnen
Rollback-Tran
Geben Sie @Err zurück
Ende
Sonst gibt 0 zurück, wenn kein Fehler vorliegt
Beginnen
Trans. begehen
Gibt 0 zurück
Ende
GEHEN
=============================================== =========================
Gespeicherte Prozedur 4: Klassifizierung anzeigen (nur eine SELECT-Anweisung)
Kategorieliste:
PROZEDUR ERSTELLEN sp_Column_List
ALS
SELECT Column_ID, Column_Name, Parent_ID, Column_Path, Column_Depth,
Column_Order, Column_Intro
VON Tb_Column
ORDER BY Column_Order
GEHEN
======================================
Hier ist ein Beispiel für die Verwendung unter ASP.NET, gepostet im Forum eines Freundes:
http://www.mzline.com/bbs/dispbbs.asp?boardID=67&ID=5044&replyID=25788&star=1&skin=0#25788