Más o menos, hemos creado menús de dos o tres niveles, como directorios de árboles y clasificaciones de productos. Si encontramos más niveles de clasificación, generalmente usamos la recursividad. El uso de la recursividad en un programa aumentará más o menos algunos gastos generales de rendimiento.
Usé ASP.net para implementar un directorio de clasificación de nivel infinito no recursivo en el programa, pero considerando que la portabilidad no es sólida, lo cambié a un procedimiento almacenado y lo envié para que todos lo estudiaran juntos. Durante el proceso de prueba, no se encontraron problemas. Además, el código no se ha optimizado.
Normalmente, la mayoría de nuestras operaciones son para leer directorios, por lo que en la siguiente implementación, solo necesitamos una instrucción Select para leer. ¡Sin recursividad, el nivel es teóricamente infinito ~!
==================================================== =====================
Estructura de la tabla:
Nombre de la tabla: Tb_Column
Estructura de la tabla (todos los campos no están vacíos):
Column_ID int clave principal (nota: no identificador)
Nombre_columna nvarchar(50) nombre de clasificación
Parent_ID int ID de categoría principal (valor predeterminado 0)
Ruta de clasificación Column_Path nvarchar(1000)
Column_Depth int profundidad de clasificación (valor predeterminado 0)
Column_Order int sort (predeterminado 0)
Column_Intro nvarchar(1000) descripción de clasificación
============================================= === ===================
Procedimiento almacenado uno: crear una nueva clasificación
CREAR PROCEDIMIENTO sp_Column_Insert
(
@Parent_ID int,
@Column_Name nvarchar(50),
@Column_Intro nvarchar(1000)
)
COMO
Declarar @Err como int
Establecer @Err=0
Iniciar tran
--Obtener el ID de la columna de los registros existentes
Declarar @Column_ID como int
Declarar @Column_Depth como int
Seleccione @Column_ID = Max(Column_ID) de Tb_Column
SI @Column_ID no es nulo
Establecer @Column_ID = @Column_ID+1
Demás
Establecer @Column_ID = 1
: determine si es una columna de nivel superior y establezca su Column_Path y Column_Order
Declarar @Column_Path como nvarchar(1000)
Declarar @Column_Order como int
SI @Parent_ID = 0
Comenzar
Establecer @Column_Path =Ltrim(Str(@Column_ID))
Seleccione @Column_Order = Max(Column_Order) de Tb_Column
SI @Column_Order no es nulo
Establecer @Column_Order = @Column_Order + 1
De lo contrario: si no se encuentra ningún registro, significa que este es el primer registro.
Establecer @Column_Order = 1
--Profundidad
Establecer @Column_Depth = 1
Fin
Demás
Comenzar
--Obtener la ruta y la profundidad del nodo principal
Seleccione @Column_Path = Column_Path, @Column_Depth = Column_Depth de Tb_Column donde
Column_ID=@Parent_ID
SI @Column_Path es nulo
Comenzar
Establecer @Err = 1
Ir al final
Fin:
obtenga el número de secuencia máximo en el mismo nodo principal
Seleccione @Column_Order = Max(Column_Order) De Tb_PicColumn Donde Column_Path como
''+@Column_Path+'|%' O Column_ID = @Parent_ID
IF @Column_Order no es nulo: si el número de secuencia existe, agregue 1 a todos los números de secuencia después del número de secuencia
Comenzar
--Actualizar los números de secuencia de todos los nodos después del nodo actual que se insertará
Actualizar Tb_Column Establecer Column_Order = Column_Order +1 Donde Column_Order
>@Column_Order
--El número de secuencia máximo bajo el mismo nodo padre más 1 forma su propio número de secuencia
Establecer @Column_Order = @Column_Order + 1
Fin
Demás
Comenzar
Establecer @Err=1
Ir al final
Fin
: la ruta del nodo principal más su propio número de identificación forman su propia ruta
Establecer @Column_Path = @Column_Path + '|' + Ltrim(Str(@Column_ID))
--Profundidad
Establecer @Column_Depth = @Column_Depth+1
final
en Tb_Column(Column_ID,Column_Name,Parent_ID,Column_Path,
Column_Depth,Column_Order,Column_Intro) Valores(@Column_ID,@Column_Name,@Parent_ID,@Column_Path,@Column_Depth,@Column_Order, @Column_Introducción )
SI @@Error<>0
Comenzar
Establecer @Err=1
Ir al final
Fin
: actualiza el ORDEN del registro después del registro actual
--Actualizar Tb_Column Establecer Column_Order = Column_Order+1 Donde Column_Order > @Column_Order
theEnd:
SI @Err=0
Comenzar
Confirmar trans
Devolver @Column_ID
Fin
Demás
Comenzar
Tran de retroceso
Devolver 0
Fin
IR
==================================================== =============================
Procedimiento almacenado dos: eliminar categoría
CREAR PROCEDIMIENTO sp_Column_Delete
(
@Column_ID entero
)
COMO
Declarar @Err como int
Establecer @Err = 0
comenzar tran
--Primero verifique si hay nodos secundarios debajo del nodo
Seleccione Column_ID de Tb_Column donde Parent_ID = @Column_ID
SI @@RowCount<>0
Comenzar
Establecer @Err = 1
Ir al final
Fin
: obtenga el Column_Order del nodo para ordenar el orden de otros registros después de la eliminación.
Declarar @Column_Order como int
Seleccione @Column_Order = Column_Order de Tb_Column donde Column_ID = @Column_ID
SI @Column_Order es NUll
Comenzar
Establecer @Err =2
Ir al final
Fin
: actualiza el Column_Order de otros registros
Actualizar Tb_Column Establecer Column_Order = Column_Order -1 Donde Column_Order >@Column_Order
SI @@Error<>0
Comenzar
Establecer @Err =3
Ir al final
Fin:
operación de eliminación
Eliminar de Tb_Column donde Column_ID=@Column_ID
SI @@Error<>0
Comenzar
Establecer @Err =4
Ir al final
Fin
: actualice el ID de columna de otros registros
--Actualizar Tb_Column Establecer Column_ID= Column_ID - 1 Donde Column_ID >@Column_ID
--SI @@Error<>0
-- Comenzar
-- Establecer @Err =5
-- Ir al final
-- Fin
del fin:
SI @Err = 0
Comenzar
Confirmar trans
Devuelve 0: eliminar correctamente
Fin
Demás
Comenzar
SI @Err=1
Comenzar
Tran de retroceso
Retorno 1: tiene nodos secundarios
Fin
Demás
Comenzar
Tran de retroceso
Devolución 2: error desconocido
Fin
Fin
IR
==================================================== =================
Procedimiento almacenado tres: editar clasificación
CREAR PROCEDIMIENTO sp_Column_Update
(
@Column_ID entero,
@Parent_ID int,
@Column_Name nvarchar(50),
@Column_Intro nvarchar(1000)
)
COMO
Declarar @Err como int
Establecer @Err=0
Comenzar transcripción:
obtenga los valores antes de la modificación: Parent_ID, Column_Depth, Column_Order
Declarar @oParent_ID como int
Declarar @oColumn_Depth como int
Declarar @oColumn_Order como int
Declare @oColumn_Path como nvarchar(1000)
Seleccione @oParent_ID = Parent_ID, @oColumn_Depth = Column_Depth, @oColumn_Order = Column_Order, @oColumn_Path = Column_Path De Tb_Column Donde Column_ID = @Column_ID
SI @oParent_ID es nulo
Comenzar
Establecer @Err = 1
Ir al final
Fin
: si la ID principal no ha cambiado, modifique directamente el nombre de la columna y la introducción de la columna.
SI @oParent_ID = @Parent_ID
Comenzar
Actualizar Tb_Column Establecer Column_Name = @Column_Name,Column_Intro = @Column_Intro Donde Column_ID = @Column_ID
SI @@Error <> 0
Establecer @Err = 2
Ir al final
Fin
Declarar @nColumn_Path como nvarchar(1000)
Declarar @nColumn_Depth como int
Declarar @nColumn_Order como int
: obtiene el número de nodos contenidos en el nodo actual como nodo principal [incluido él mismo] Nota: si se devuelve "1", significa que es un nodo único
Declarar @theCount como int
Seleccione @theCount = Count(Column_ID) de Tb_Column donde Column_ID=@Column_ID o Column_Path como ''+@oColumn_Path+'|%'
SI @theCount es nulo
Comenzar
Establecer @Err = 3
Ir al final
End
IF @Parent_ID=0: si está configurado como un nodo de nivel superior, establezca el nodo en el último nodo de nivel superior
Comenzar
--Imprimir 'Establecer como columna de nivel superior'
Establecer @nColumn_Path = Ltrim(Str(@Column_ID))
Establecer @nColumn_Depth =1
Seleccionar @nColumn_Order = Max(Column_Order) de Tb_Column
SI @nColumn_Order es NULO
Comenzar
Establecer @Err = 4
Ir al final
End
Set @nColumn_Order = @nColumn_Order - @theCount + 1
--Actualizar tres partes 1 El nodo en sí 2 Todos los nodos secundarios 2 El orden de los registros posteriores antes de que cambie este árbol
--Imprimir 'Actualizar todas las columnas después de la posición anterior de esta columna [excluyendo las subcolumnas debajo de esta columna]: Column_Order'
Actualizar Tb_Column Establecer Column_Order = Column_Order-@theCount Donde (Column_Order >@oColumn_Order) y (Column_Path No como ''+@oColumn_Path+'|%' )
SI @@Error <> 0
Comenzar
Establecer @Err = 7
Ir al final
End
--Print 'Actualizar esta columna: ID_principal, Ruta_columna, Profundidad_columna, Orden_columna, Nombre_columna, Introducción_columna'
Imprimir 'Pedido: '+Ltrim(Str(@nColumn_Order))
Actualizar Tb_Column Set Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro Donde Column_ID = @Column_ID
SI @@Error <> 0
Comenzar
Establecer @Err = 5
Ir al final
Fin
--Imprimir 'Actualizar todas las subcolumnas de esta columna: Ruta_columna, Profundidad_columna, Orden_columna'
Actualizar Tb_Column Establecer Column_Path = Reemplazar(Column_Path,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth-@oColumn_Depth),Column_Order = Column_Order+( @nColumn_Order-@oColumn_Order) Donde Column_Path es como ''+@oColumn_Path+' |%'
SI @@Error <> 0
Comenzar
Establecer @Err = 6
Ir al final
Fin
Fin
Demás
Comenzar
--Obtenga la información relevante del futuro nodo padre y establezca los valores relevantes de este nodo
Seleccione @nColumn_Depth = Column_Depth, @nColumn_Path = Column_Path de Tb_Column donde Column_ID = @Parent_ID
SI @nColumn_Depth es NULL o @nColumn_Path es nulo
Comenzar
Establecer @Err = 8
Ir al final
Fin
Establecer @nColumn_Depth = @nColumn_Depth +1
Seleccione @nColumn_Order =Max(Column_Order) De Tb_Column Donde Column_ID = @Parent_ID O Column_Path como ''+@nColumn_Path+'|%'
SI @nColumn_Order es NULO
Comenzar
Establecer @Err = 9
Ir al final
End
Set @nColumn_Path = @nColumn_Path +'|'+ Ltrim(Str(@Column_ID))
IF @nColumn_Order = @oColumn_Order+1 --Si el nuevo nodo padre es el hermano más cercano por encima de la posición original, el orden de todos los nodos será ser diferente.
Comenzar
Actualizar Tb_Column Set Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth, Column_Name = @Column_Name,Column_Intro = @Column_Intro Donde Column_ID = @Column_ID
SI @@Error <> 0
Comenzar
Establecer @Err = 10
Ir al final
Fin
final
@nColumn_Order = @nColumn_Order + 1
--Actualizar tres partes 1 El orden de los registros siguientes (o anteriores) antes de que cambie este árbol 1 El nodo en sí 3 Todos los nodos secundarios
--Dividido en movimiento ascendente o movimiento descendente
--Imprimir 'Actualizar todas las columnas después de la posición anterior de esta columna [o la posición después de esta columna] [excluyendo las subcolumnas de esta columna]: Column_Order'
SI @nColumn_Order < @oColumn_Order
Comenzar
Actualizar Tb_Column Establecer Column_Order = Column_Order+@theCount Donde Column_Order<@oColumn_Order And Column_Order >=@nColumn_Order Y (Column_Path No como ''+@oColumn_Path+'|%' ) Y Column_ID<>@Column_ID
SI @@Error <> 0
Comenzar
Establecer @Err = 12
Ir al final
Fin
Fin
Demás
Comenzar
Actualizar Tb_Column Establecer Column_Order = Column_Order-@theCount Donde Column_Order >@oColumn_Order Y Column_Order<@nColumn_Order Y (Column_Path No como ''+@oColumn_Path+'|%' ) Y Column_ID<>@Column_ID
SI @@Error <> 0
Comenzar
Establecer @Err = 13
Ir al final
Fin
End
--Print 'Actualizar esta columna: ID_principal, Ruta_columna, Profundidad_columna, Orden_columna, Nombre_columna, Introducción_columna'
Imprimir 'Pedido: '+Ltrim(Str(@nColumn_Order))
SI @nColumn_Order > @oColumn_Order
Establecer @nColumn_Order = @nColumn_Order - @theCount
Actualizar Tb_Column Set Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro Donde Column_ID = @Column_ID
SI @@Error <> 0
Comenzar
Establecer @Err = 10
Ir al final
Fin
--Imprimir 'Actualizar todas las subcolumnas de esta columna: Column_Paht, Column_Depth, Column_Order'
Actualizar Tb_Column Establecer Column_Path = Reemplazar(Column_Depth,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth-@oColumn_Depth),Column_Order = Column_Order+(@nColumn_Order-@oColumn_Order) Donde Column_Path es como ''+@oColumn_Path+' |%'
SI @@Error <> 0
Comenzar
Establecer @Err = 11
Ir al final
Fin
Termina
el fin:
IF @Err<>0: si hay un error, devuelve el número de error
Comenzar
Tran de retroceso
Devolver @Error
Fin
De lo contrario, devuelve 0 si no hay ningún error.
Comenzar
Confirmar trans
Devolver 0
Fin
IR
==================================================== ===========================
Procedimiento almacenado cuatro: clasificación de visualización (solo una declaración de selección)
Lista de categorías:
CREAR PROCEDIMIENTO sp_Column_List
COMO
SELECCIONE ID_columna, Nombre_columna, ID_principal, Ruta_columna, Profundidad_columna,
Orden_columna, Introducción_columna
DESDE Tb_Column
ORDENAR POR Columna_Orden
IR
=========================================
A continuación se muestra un ejemplo de uso en ASP.NET, publicado en el foro de un amigo:
http://www.mzline.com/bbs/dispbbs.asp?boardID=67&ID=5044&replyID=25788&star=1&skin=0#25788