Tengo una tabla con la siguiente estructura:
Código SQL
[-]CREATE TABLE Arbol (
IDOPCION INT NOT NULL,
IDPADRE INT NOT NULL DEFAULT 0,
DESCRIPCION VARCHAR(50),
CONSTRAINT ArbolKey PRIMARY KEY (IDOPCION))
En esa tabla guardo la información de la estructura ciclica.
El siguiente procedimiento me devuelve la información de la tabla
Código SQL
[-]
CREATE PROCEDURE Arbol_ABM_Opciones
-- =============================================
-- Author: Juan Carlos Arteaga
-- Create date: 17/08/2008
-- Description: Genera el Arbol de Opciones para el ABM
-- =============================================
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #work (lvl int, IdOpcion int)
CREATE TABLE #Opciones (seq int identity, lvl int, IdOpcion int)
DECLARE @lvl int, @curr int
SET @lvl=1
INSERT INTO #work (lvl, IdOpcion)
SELECT 1,IDOPCION
FROM Arbol
WHERE IdPadre=0
WHILE (@lvl > 0)
BEGIN
IF EXISTS(SELECT * FROM #work WHERE lvl=@lvl)
BEGIN
SELECT TOP 1 @curr=IdOpcion FROM #work
WHERE lvl=@lvl
INSERT #Opciones (lvl, IdOpcion) VALUES (@lvl, @curr)
DELETE #work
WHERE lvl=@lvl and IdOpcion=@curr
INSERT #work
SELECT @lvl+1, IdOpcion
FROM Arbol
WHERE IdPadre=@curr
AND IdPadre <> IdOpcion
IF (@@ROWCOUNT > 0)
SET @lvl=@lvl+1
END
ELSE
SET @lvl=@lvl-1
END
SELECT d.seq,d.IdOpcion,i.Descripcion,i.IdPadre
FROM #Opciones d
JOIN Arbol i ON (d.IdOpcion=i.IdOpcion)
ORDER BY seq
DROP TABLE #Work
DROP Table #Opciones
END
Todos los nodos raiz (puedo tener mas de uno) tienen como padre el valor 0.
Ya en Delphi cargo esta estructura en un TTreeView (tvDatos) usando el siguiente procedimiento (spArbolABM es el TADOStoredProc que llama al anterior Procedimiento Almacenado):
Código Delphi
[-]Type
PItem = ^TItem;
TItem = record
IdOpcion : integer;
end;
...
var
tnNodoActual : TTreeNode;
...
procedure TfrmABMMenu.Cargar_Arbol;
var
TPrimerNodo: TTreeNode;
i: integer;
MyItem : PItem;
procedure Rama(iCodigo: Integer; NodoPadre: TTreeNode);
var
iCodPadre: integer;
TNodoPadre: TTreeNode;
begin
if (spArbolABMIDPADRE.Value = iCodigo) then
while (spArbolABMIDPADRE.Value = iCodigo) and (not spArbolABM.EOF) do
begin
inc(i);
new(MyItem);
MyItem.IdOpcion := spArbolABMIDOPCION.AsInteger;
TNodoPadre := tvDatos.Items.AddChildObject(NodoPadre,
spArbolABMDESCRIPCION.AsString,MyItem);
iCodPadre := spArbolABMIDOPCION.Value;
spArbolABM.Next;
Application.ProcessMessages;
Rama(iCodPadre, TNodoPadre);
end;
end;
begin
i := 0;
tvDatos.Items.Clear;
spArbolABM.close;
spArbolABM.Open;
Screen.Cursor := crHourGlass;
try
if not spArbolABM.IsEmpty then
Rama(0, nil);
finally
Screen.Cursor := crDefault;
tvDatos.Selected := tvDatos.Items.GetFirstNode;
tnNodoActual := tvDatos.Selected;
end;
spArbolABM.close;
end;
Espero que sea de utilidad.
Saludos