Funcţie recursivă cu cursor - un model redus al unei aplicatii de tip forum

 

[Home] Funcţie recursivă cu cursor - un model redus al unei aplicaţii de tip forum

Exemplul următor poate fi utilizate pentru dezvoltarea unei aplicatii tip forum de discutii.

1. Tabela de utilizatori

Primul tabel utilizat într-o o aplicatie de tip forum este tabela de utilizatori:
----------------------------------------------------------
-- Users
-----------------------------------------------------------

CREATE TABLE Users
(
     [ID] INT PRIMARY KEY IDENTITY,
     UserName VARCHAR (30) NOT NULL,
     [Password] NVARCHAR (60) NOT NULL,
     Email VARCHAR (100) NOT NULL
)

2. Tabela de mesaje

Apoi se defineste tabela de mesaje:
----------------------------------------------------------
-- Messages
-----------------------------------------------------------

CREATE TABLE Messages
(
     [ID] INT PRIMARY KEY IDENTITY,
     UserID INT REFERENCES Users ([ID]) NOT NULL,
     [Date] DATETIME DEFAULT GetDate(),
     Message NVARCHAR (4000) NOT NULL,
     ParentMessage INT REFERENCES Messages ([ID])
)

In acest tabel campul ParentMessage contine ID-ul mesajului parinte. Un mesaj care are ParentMessage NOT NULL
este un raspuns la mesajul cu ID-ul din acest camp.
In acest fel tabela "Messages" descrie mai multi arbori, cu radacinile in acele inregistrari care au ID-ul nul.
Pentru a obţine ramurile unui arbore vom utiliza o funţie recursivă.


3. Inserarea de valori

Inserarea de valori in cele două tabele:
----------------------------------------------------------
-- Inserting values into Users table -----------------------------------------------------------

INSERT INTO Users VALUES ('aionescu', 'pwd', 'adi_ionescu@rol.ro')

----------------------------------------------------------
-- Inserting values into Messages tablee
-----------------------------------------------------------

INSERT INTO Messages VALUES (1, DEFAULT, 'first message', null)
--responses to the first message (ID = 1)
INSERT INTO Messages VALUES (1, DEFAULT, 'first response', 1)
INSERT INTO Messages VALUES (1, DEFAULT, 'second response', 1)

4. Obţinerea detaliilor unui mesaj

Se utilizează un query de genul:

----------------------------------------------------------
-- Selecting message details
-----------------------------------------------------------

SELECT Messages.[Date], Messages.Message, Users.UserName, Users.Email
FROM Messages
INNER JOIN Users ON Messages.UserID = Users.[ID]
WHERE Messages.[ID] = 1

Rezultat:

Date Message UserName Email
2002-10-26 12:41:59.310 first message aionescu adi_ionescu@rol.ro


5. Funcţia recursivă

In conţinutul funcţiei puteţi găsi comentarii utile:
----------------------------------------------------------------------------------------
--Functia: fGetMessageChilds
--Parametri IN: @ID INT - este un ID diin tabela Messages
--Parametri OUT: @tbl TABLE - functia reeturneaza un tabel
--Descriere: returneaza raspunsurile daate mesajului cu ID dat, precum si raspunsurile
-- primite de acestea
-----------------------------------------------------------------------------------------

CREATE FUNCTION fGetMessageChilds (@ID INT)
    --functia returneaza un tabel:
    RETURNS @tbl TABLE ([ID] INT, UserID INT, [Date] DATETIME, Message NVARCHAR (4000), ParentMessage INT)
AS

BEGIN

--declararea variabilei pentru navigarea intre inregistrarile din cursor
DECLARE @i INT

--declararea cursorului
DECLARE c CURSOR FOR
SELECT [ID]
FROM Messages
WHERE ParentMessage = @ID

OPEN c
--navigarea la prima inregistrare din cursor
FETCH NEXT FROM c INTO @i

WHILE @@FETCH_STATUS = 0
BEGIN
     INSERTINTO @tbl
     SELECT [ID], UserID, [Date], Message, ParentMessage
     FROM Messages
     WHERE [ID] = @i

     --apelul recursiv al functiei
     INSERT INTO @tbl SELECT [ID], UserID, [Date], Message, ParentMessage FROM fGetMessageChilds (@i)

     --avans la urmatorul rand al cursorului
     FETCH NEXT FROM c INTO @i
END

CLOSE c
DEALLOCATE c

RETURN

END

GO

6. Utilizarea funcţiei

Pentru a vedea toate răspunsurile date mesajului cu ID-ul 1 se utilizează:
SELECT * FROM fGetMessageChilds (1)

Notă importantă: numărul maxim de recurenţe permise este de 32!