Avatar billede hojgaard Nybegynder
12. september 2008 - 11:30 Der er 5 kommentarer og
2 løsninger

Stored procedure med rekursiv select og delete

Hej

Jeg vil gerne have lavet en stored procedure, der ud fra et ItemID, rekursivt kan finde alle children.
Jeg skal bruge denne funktion til både SELECT og DELETE.

Min tabel 'Item' indeholder 2 UNIQUEIDENTIFIERs 'ItemID' og 'ParentID'. ItemID er primærnøgle og ParentID peger på det item, som det er placeret under.

Sådan kunne en struktur f.eks. se ud (der er ikke et max antal levels).

- Item1
- Item2
    - Item2a
    - Item2b
        - Item2b1
            - Item2b1a
            - Item2b1b
        - Item2b2
        - Item2b3
    - Item2c
    - Item2d
- Item3
- Item4

Jeg har prøvet mig lid frem, med denne SP, men den giver mig kun første Item.

CREATE PROCEDURE [dbo].[DeleteItem]
    @ItemID UNIQUEIDENTIFIER
AS
BEGIN
    DECLARE @ItemsToDelete TABLE (ID UNIQUEIDENTIFIER);

    INSERT INTO @ItemsToDelete (ID) VALUES (@ItemID);

    WHILE @@ROWCOUNT <> 0
    BEGIN
        INSERT INTO @ItemsToDelete
            SELECT ItemID FROM Item WHERE ParentID IN (SELECT ID FROM @ItemsToDelete) AND NOT ItemID IN (SELECT ItemID FROM @ItemsToDelete);
    END

    --DELETE FROM Item WHERE ItemID IN ( SELECT ID FROM @ItemsToDelete );
    SELECT * FROM @ItemsToDelete
END
Avatar billede aaberg Nybegynder
12. september 2008 - 13:34 #1
Jeg vil foreslå at du laver en trigger som bliver kørt, hver gang en række bliver slettet. Denne trigger skal så slette alle rækker hvor ItemID er lig med den slettede rækkes ParentID. Dette vil starte en rekursiv sletning af alle children.

Så skal du i din stored procedure bare slette den række der ligger øverst i hirakiet, og resten vil automatisk følge efter.
Avatar billede hojgaard Nybegynder
12. september 2008 - 14:34 #2
Tak for svaret aaberg... men jeg tror jeg har fået løst det uden brug af trigger.


CREATE PROCEDURE [dbo].[SelectWithChildren]
    @ItemID UNIQUEIDENTIFIER
AS
BEGIN
    WITH RecursiveList(ItemID, ParentID, Name) AS
    (
        SELECT ItemID, ParentID, Name FROM Item
        WHERE ItemID = @ItemID
       
        UNION ALL
       
        SELECT e.ItemID, e.ParentID, e.Name FROM Item e
        INNER JOIN RecursiveList d ON d.ItemID = e.ParentID
    )
    SELECT * FROM RecursiveList;
END

Forbedringer er naturligvis velkommen ;)
Avatar billede aaberg Nybegynder
12. september 2008 - 14:41 #3
Genialt at bruge WITH, den havde jeg ikke tænkt på! :-)
Avatar billede michaelthomsendk Nybegynder
12. september 2008 - 14:42 #4
Dit oprindelig forslag virker faktisk

SELECT ItemID FROM Item WHERE ParentID IN (SELECT ID FROM @ItemsToDelete)
AND NOT ItemID IN (SELECT !!!ItemID!!! FROM @ItemsToDelete);

Bortset fra !!!ItemID!!! skal være ID

:-)
Avatar billede hojgaard Nybegynder
16. september 2008 - 10:33 #5
Tak for løsningen på mit første statement michaelthomsendk!

Smider i begge ikke et svar... så lukker jeg tråden ;o)
Avatar billede michaelthomsendk Nybegynder
16. september 2008 - 10:45 #6
Jeps :-)
Avatar billede aaberg Nybegynder
16. september 2008 - 11:27 #7
svar :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester