Plus ou moins, nous avons réalisé des menus à deux ou trois niveaux comme des arborescences et des classifications de produits. Si nous rencontrons plus de niveaux de classification, nous utilisons généralement la récursion. L'utilisation de la récursivité dans un programme augmentera plus ou moins certaines performances.
J'ai déjà utilisé ASP.net pour implémenter un répertoire de classification non récursif à niveau infini dans le programme, mais étant donné que la portabilité n'est pas forte, je l'ai changé en procédure stockée et je l'ai envoyé pour que tout le monde puisse étudier ensemble. Au cours du processus de test, aucun problème n’a été détecté. De plus, le code n’a pas été optimisé.
Normalement, la plupart de nos opérations consistent à lire des répertoires, donc dans l'implémentation suivante, nous n'avons besoin que d'une seule instruction Select pour lire. Sans récursion, le niveau est théoriquement infini ~ !
=================================================== ====================
Structure du tableau :
Nom de la table : Tb_Column
Structure du tableau (tous les champs ne sont pas vides) :
Column_ID int clé primaire (remarque : non-identifiant)
Nom_colonne nvarchar(50) nom de classification
Parent_ID int ID de catégorie parent (valeur par défaut 0)
Chemin de classification Column_Path nvarchar(1000)
Column_Depth int profondeur de classification (valeur par défaut 0)
Tri int Column_Order (par défaut 0)
Column_Intro nvarchar(1000) description de la classification
============================================ === ==================
Procédure stockée 1 : Créer une nouvelle classification
CREATE PROCEDURE sp_Column_Insert
(
@Parent_ID entier,
@Nom_Colonne nvarchar(50),
@Column_Intro nvarchar(1000)
)
COMME
Déclarez @Err As int
Définir @Err=0
Commencer Tran
--Obtenir l'ID de colonne à partir des enregistrements existants
Déclarez @Column_ID comme int
Déclarez @Column_Depth comme int
Sélectionnez @Column_ID = Max(Column_ID) à partir de Tb_Column
SI @Column_ID n'est pas nul
Définir @Column_ID = @Column_ID+1
Autre
Set @Column_ID = 1
-- Déterminez s'il s'agit d'une colonne de niveau supérieur et définissez ses Column_Path et Column_Order
Déclarez @Column_Path comme nvarchar(1000)
Déclarez @Column_Order comme int
SI @Parent_ID = 0
Commencer
Définir @Column_Path =Ltrim(Str(@Column_ID))
Sélectionnez @Column_Order = Max(Column_Order) à partir de Tb_Column
SI @Column_Order n'est pas nul
Définir @Column_Order = @Column_Order + 1
Sinon --Si aucun enregistrement n'est trouvé, cela signifie qu'il s'agit du premier enregistrement
Définir @Column_Order = 1
--Profondeur
Définir @Column_Depth = 1
Fin
Autre
Commencer
--Obtenir le chemin et la profondeur du nœud parent
Sélectionnez @Column_Path = Column_Path ,@Column_Depth = Column_Depth From Tb_Column Où
Column_ID=@Parent_ID
SI @Column_Path est nul
Commencer
Définir @Err = 1
Aller jusqu'au bout
Fin
--Obtenir le numéro de séquence maximum sous le même nœud parent
Sélectionnez @Column_Order = Max(Column_Order) From Tb_PicColumn Où Column_Path comme
''+@Column_Path+'|%' Ou Column_ID = @Parent_ID
IF @Column_Order Is Not Null --Si le numéro de séquence existe, ajoutez 1 à tous les numéros de séquence après le numéro de séquence
Commencer
--Mettre à jour les numéros de séquence de tous les nœuds après le nœud actuel à insérer
Mettre à jour Tb_Column Définir Column_Order = Column_Order +1 Où Column_Order
>@Column_Order
--Le numéro de séquence maximum sous le même nœud parent plus 1 forme son propre numéro de séquence
Définir @Column_Order = @Column_Order + 1
Fin
Autre
Commencer
Définir @Err=1
Aller jusqu'au bout
Fin
--Le chemin du nœud parent plus son propre numéro d'identification forment son propre chemin
Définir @Column_Path = @Column_Path + '|' + Ltrim(Str(@Column_ID))
--Profondeur
Définir @Column_Depth = @Column_Depth+1
Fin
Insérer dans Tb_Column (Column_ID,Column_Name,Parent_ID,Column_Path,
Column_Depth,Column_Order,Column_Intro) Valeurs (@Column_ID,@Column_Name,@Parent_ID,@Column_Path,@Column_Depth,@Column _Order,@ Colonne_Intro )
SI @@Erreur<>0
Commencer
Définir @Err=1
Aller jusqu'au bout
Fin
- Mettre à jour l'ORDRE de l'enregistrement après l'enregistrement en cours
--Mise à jour Tb_Column Set Column_Order = Column_Order+1 Où Column_Order > @Column_Order
theEnd :
SI @Err=0
Commencer
Valider la transmission
Retourner @Column_ID
Fin
Autre
Commencer
Annulation de la transaction
Retour 0
Fin
ALLER
================================================== ============================
Procédure stockée deux : supprimer la catégorie
CRÉER UNE PROCÉDURE sp_Column_Delete
(
@Column_ID entier
)
COMME
Déclarez @Err As int
Définir @Err = 0
Commencer la transition
--Vérifiez d'abord s'il y a des nœuds enfants sous le nœud
Sélectionnez Column_ID dans Tb_Column où Parent_ID = @Column_ID
SI @@RowCount<>0
Commencer
Définir @Err = 1
Aller jusqu'au bout
End
-- Récupère le Column_Order du nœud, afin de trier l'ordre des autres enregistrements après suppression
Déclarez @Column_Order comme int
Sélectionnez @Column_Order = Column_Order depuis Tb_Column où Column_ID = @Column_ID
SI @Column_Order est NULL
Commencer
Définir @Err =2
Aller jusqu'au bout
Fin
- Mettre à jour le Column_Order des autres enregistrements
Mettre à jour Tb_Column Définir Column_Order = Column_Order -1 Où Column_Order >@Column_Order
SI @@Erreur<>0
Commencer
Définir @Err =3
Aller jusqu'au bout
Terminer
l'opération --delete
Supprimer de Tb_Column où Column_ID=@Column_ID
SI @@Erreur<>0
Commencer
Définir @Err =4
Aller jusqu'au bout
Fin
--Mettre à jour le Column_ID des autres enregistrements
--Mise à jour Tb_Column Set Column_ID= Column_ID - 1 Où Column_ID >@Column_ID
--SI @@Erreur<>0
-- Commencer
-- Définir @Err =5
- Aller jusqu'au bout
-- Fin de
laFin :
SI @Err = 0
Commencer
Valider la transmission
Renvoie 0 --Supprimer avec succès
Fin
Autre
Commencer
SI @Err=1
Commencer
Annulation de la transaction
Retour 1 --a des nœuds enfants
Fin
Autre
Commencer
Annulation de la transaction
Retour 2 – Erreur inconnue
Fin
Fin
ALLER
=================================================== ================
Procédure stockée trois : Modifier la classification
CRÉER UNE PROCÉDURE sp_Column_Update
(
@Column_ID entier,
@Parent_ID entier,
@Nom_Colonne nvarchar(50),
@Column_Intro nvarchar(1000)
)
COMME
Déclarez @Err As int
Set @Err=0
Begin Tran
--Obtenir les valeurs avant modification : Parent_ID, Column_Depth, Column_Order
Déclarez @oParent_ID comme int
Déclarez @oColumn_Depth comme int
Déclarez @oColumn_Order comme int
Déclarez @oColumn_Path comme nvarchar (1000)
Sélectionnez @oParent_ID = Parent_ID, @oColumn_Depth = Column_Depth, @oColumn_Order = Column_Order, @oColumn_Path = Column_Path From Tb_Column Où Column_ID = @Column_ID
SI @oParent_ID est nul
Commencer
Définir @Err = 1
Aller jusqu'au bout
Fin
--Si l'ID parent n'a pas changé, modifiez directement le nom de la colonne et l'introduction de la colonne.
SI @oParent_ID = @Parent_ID
Commencer
Mettre à jour Tb_Column Définir Column_Name = @Column_Name,Column_Intro = @Column_Intro Où Column_ID = @Column_ID
SI @@Erreur <> 0
Définir @Err = 2
Aller jusqu'au bout
Fin
Déclarez @nColumn_Path comme nvarchar(1000)
Déclarez @nColumn_Depth comme int
Déclarer @nColumn_Order As int
-- Obtenez le nombre de nœuds contenus dans le nœud actuel en tant que nœud parent [y compris lui-même] Remarque : Si "1" est renvoyé, cela signifie qu'il s'agit d'un nœud unique.
Déclarez @theCount Comme int
Sélectionnez @theCount = Count(Column_ID) From Tb_Column Where Column_ID=@Column_ID Ou Column_Path comme ''+@oColumn_Path+'|%'
SI @theCount est nul
Commencer
Définir @Err = 3
Aller jusqu'au bout
End
IF @Parent_ID=0 --S'il est défini comme nœud de niveau supérieur, définissez le nœud sur le dernier nœud de niveau supérieur
Commencer
--Print 'Définir comme colonne de niveau supérieur'
Définir @nColumn_Path = Ltrim(Str (@Column_ID))
Définir @nColumn_Depth =1
Sélectionner @nColumn_Order = Max(Column_Order) à partir de Tb_Column
SI @nColumn_Order est NULL
Commencer
Définir @Err = 4
Aller jusqu'au bout
End
Set @nColumn_Order = @nColumn_Order - @theCount + 1
--Mettre à jour trois parties 1 Le noeud lui-même 2 Tous les noeuds enfants 2 L'ordre des enregistrements suivants avant que cet arbre ne change
--Print 'Mettre à jour toutes les colonnes après la position précédente de cette colonne [à l'exclusion des sous-colonnes sous cette colonne] : Column_Order'
Mettre à jour Tb_Column Set Column_Order = Column_Order-@theCount Où (Column_Order >@oColumn_Order) Et (Column_Path Pas comme ''+@oColumn_Path+'|%' )
SI @@Erreur <> 0
Commencer
Définir @Err = 7
Aller jusqu'au bout
End
--Print 'Mettre à jour cette colonne : Parent_ID, Column_Path, Column_Depth, Column_Order, Column_Name, Column_Intro'
Imprimer 'Commande : '+Ltrim(Str(@nColumn_Order))
Mettre à jour Tb_Column Définir Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro Où Column_ID = @Column_ID
SI @@Erreur <> 0
Commencer
Définir @Err = 5
Aller jusqu'au bout
End
--Print 'Mettre à jour toutes les sous-colonnes de cette colonne : Column_Path, Column_Depth, Column_Order'
Mettre à jour Tb_Column Set Column_Path = Replace(Column_Path,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth-@oColumn_Depth),Column_Order = Column_Order+( @nColumn_Order-@oColumn_Order) Où Column_Path comme ''+@oColumn_Path+' |%'
SI @@Erreur <> 0
Commencer
Définir @Err = 6
Aller jusqu'au bout
Fin
Fin
Autre
Commencer
--Obtenez les informations pertinentes du futur nœud parent et définissez les valeurs pertinentes de ce nœud
Sélectionnez @nColumn_Depth = Column_Depth, @nColumn_Path = Column_Path From Tb_Column Où Column_ID = @Parent_ID
SI @nColumn_Depth est NULL ou @nColumn_Path est NULL
Commencer
Définir @Err = 8
Aller jusqu'au bout
Fin
Définir @nColumn_Depth = @nColumn_Depth +1
Sélectionnez @nColumn_Order =Max(Column_Order) From Tb_Column Where Column_ID = @Parent_ID Ou Column_Path comme ''+@nColumn_Path+'|%'
SI @nColumn_Order est NULL
Commencer
Définir @Err = 9
Aller jusqu'au bout
End
Set @nColumn_Path = @nColumn_Path +'|'+ Ltrim(Str(@Column_ID))
IF @nColumn_Order = @oColumn_Order+1 --Si le nouveau nœud parent est le frère le plus proche au-dessus de la position d'origine, l'ordre de tous les nœuds sera être différent.
Commencer
Mettre à jour Tb_Column Définir Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth, Column_Name = @Column_Name,Column_Intro = @Column_Intro Où Column_ID = @Column_ID
SI @@Erreur <> 0
Commencer
Définir @Err = 10
Aller jusqu'au bout
Fin
End
Set @nColumn_Order = @nColumn_Order + 1
--Mettre à jour trois parties 1 L'ordre des enregistrements suivants (ou précédents) avant que cet arbre ne change 1 Le noeud lui-même 3 Tous les noeuds enfants
--Divisé en mouvement ascendant ou mouvement descendant
--Print 'Mettre à jour toutes les colonnes après la position précédente de cette colonne [ou la position après cette colonne] [à l'exclusion des sous-colonnes sous cette colonne] : Column_Order'
SI @nColumn_Order < @oColumn_Order
Commencer
Mettre à jour Tb_Column Définir Column_Order = Column_Order+@theCount Où Column_Order<@oColumn_Order Et Column_Order >=@nColumn_Order Et (Column_Path Pas comme ''+@oColumn_Path+'|%' ) Et Column_ID<>@Column_ID
SI @@Erreur <> 0
Commencer
Définir @Err = 12
Aller jusqu'au bout
Fin
Fin
Autre
Commencer
Mettre à jour Tb_Column Définir Column_Order = Column_Order-@theCount Où Column_Order >@oColumn_Order Et Column_Order<@nColumn_Order Et (Column_Path Pas comme ''+@oColumn_Path+'|%' ) Et Column_ID<>@Column_ID
SI @@Erreur <> 0
Commencer
Définir @Err = 13
Aller jusqu'au bout
Fin
End
--Print 'Mettre à jour cette colonne : Parent_ID, Column_Path, Column_Depth, Column_Order, Column_Name, Column_Intro'
Imprimer 'Commande : '+Ltrim(Str(@nColumn_Order))
SI @nColumn_Order > @oColumn_Order
Définir @nColumn_Order = @nColumn_Order - @theCount
Mettre à jour Tb_Column Définir Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro Où Column_ID = @Column_ID
SI @@Erreur <> 0
Commencer
Définir @Err = 10
Aller jusqu'au bout
End
--Print 'Mettre à jour toutes les sous-colonnes de cette colonne : Column_Paht, Column_Depth, Column_Order'
Mettre à jour Tb_Column Set Column_Path = Replace(Column_Path,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth-@oColumn_Depth),Column_Order = Column_Order+ (@nColumn_Order-@oColumn_Order) Où Column_Path comme ''+@oColumn_Path+'| %'
SI @@Erreur <> 0
Commencer
Définir @Err = 11
Aller jusqu'au bout
Fin
Fin
de la fin :
IF @Err<>0 --S'il y a une erreur, renvoie le numéro d'erreur
Commencer
Annulation de la transaction
Retour @Err
Fin
Sinon --renvoie 0 s'il n'y a pas d'erreur
Commencer
Valider la transmission
Retour 0
Fin
ALLER
=================================================== =========================
Procédure stockée quatre : affichage de la classification (juste une instruction de sélection)
Liste des catégories :
CRÉER UNE PROCÉDURE sp_Column_List
COMME
SELECT ID_colonne, Nom_colonne, ID_parent, Chemin_colonne, Profondeur_colonne,
Colonne_Ordre, Colonne_Intro
DE Tb_Column
COMMANDE PAR Colonne_Ordre
ALLER
=======================================
Voici un exemple d'utilisation sous ASP.NET, posté sur le forum d'un ami :
http://www.mzline.com/bbs/dispbbs.asp?boardID=67&ID=5044&replyID=25788&star=1&skin=0#25788