Arjuna Aircraft Ident.: F-MBSD | Salut,
J'ai un léger problème avec SQL Server 2000
J'ai fait une procédure stockée, qui est récursive (elle s'appelle elle-même) et elle contient un curseur.
En fait, c'est dans la boucle du curseur qu'elle s'appelle elle-même, et il semble que le problème vienne de là.
En effet, lorsque je l'éxécute, voici les erreurs que j'obtiens :
Code :
- Serveur : Msg 16915, Niveau 16, État 1, Procédure objDelete, Ligne 21
- Un curseur nommé 'fils' existe déjà.
- Serveur : Msg 16915, Niveau 16, État 1, Procédure objDelete, Ligne 21
- Un curseur nommé 'fils' existe déjà.
- Serveur : Msg 16905, Niveau 16, État 1, Procédure objDelete, Ligne 26
- Le curseur est déjà ouvert.
- (1 ligne(s) affectée(s))
- Serveur : Msg 16916, Niveau 16, État 1, Procédure objDelete, Ligne 35
- Un curseur nommé 'fils' n'existe pas.
- Serveur : Msg 16916, Niveau 16, État 1, Procédure objDelete, Ligne 38
- Un curseur nommé 'fils' n'existe pas.
- Serveur : Msg 16916, Niveau 16, État 1, Procédure objDelete, Ligne 39
- Un curseur nommé 'fils' n'existe pas.
- (1 ligne(s) affectée(s))
|
Voici le code de ma procédure :
Code :
- CREATE PROCEDURE dbo.objDelete(@usrlog as varchar(50), @objnum as numeric, @typobj as char(3))
- AS
- begin
- declare @nb as numeric
- -- On vérifie qu'il n'y a pas de fils encore actifs (interdit)
- select @nb = count(*) from obj where typpar = upper(@typobj) and objpar = @objnum and objsta != 'D'
- if @nb > 0
- begin
- RAISERROR ('Impossible de supprimer un noeud ayant encore des fils non supprimés', 16, 1)
- end
- -- Maintenant, on regarde le status. Si le noeud est déjà flagé comme supprimé, on le supprime pour de bon ainsi que tous ses fils, sinon on le marque comme supprimé
- declare @objsta as char(1)
- select @objsta = objsta from obj where typobj = upper(@typobj) and objnum = @objnum
- if @objsta != 'D'
- begin
- -- On flag le noeud actif en supprimé
- update obj set objsta = 'D', usrmod = upper(@usrlog), dtemod = getDate() where typobj = upper(@typobj) and objnum = @objnum
- end
- else
- begin
- -- On va supprimer tous les fils déjà supprimés (grace au check initial, si on est ici, c'est que les eventuels fils sont déjà forcément flagé comme supprimés)
- declare @filsnum as numeric
- declare @filstyp as char(3)
- DECLARE fils CURSOR FOR
- SELECT objnum, typobj
- FROM obj
- WHERE objsta = 'D'
- AND typpar = upper(@typobj) and objpar = @objnum
- OPEN fils
- FETCH NEXT FROM fils
- INTO @filsnum, @filstyp
- WHILE @@FETCH_STATUS = 0
- BEGIN
- -- On supprime chaque fils (appel récursif, afin de contrôler les petits-fils)
- execute objDelete @usrlog, @filsnum, @filstyp
- FETCH NEXT FROM fils
- INTO @filsnum, @filstyp
- END
- CLOSE fils
- DEALLOCATE fils
- -- On supprime définitivement le noeud flagé comme supprimé
- delete obj where typobj = upper(@typobj) and objnum = @objnum and objsta = 'D'
- end
- end
- GO
|
Contenu de la base au moment de l'erreur (les fils de l'article 1 sont au status "D", et lui-même aussi. :
Code :
- objnum typobj objsta objnam objpar typpar
- -------------------- ------ ------ -------------------------------------------------- -------------------- ------
- 1 ART D Article 1 NULL NULL
- 1 REP D Chapitre 1 1 ART
- 2 ART C Article 2 NULL NULL
- 2 REP D Chapitre 2 1 ART
- 3 REP C Chapitre 1 2 ART
- 4 REP C Chapitre 2 2 ART
|
Commande exécutée :
Code :
- execute objDelete 'SDEVIDAL', 1, 'ART'
|
Les autres étapes se sont bien déroulées :
Code :
- execute objDelete 'SDEVIDAL', 1, 'ART'
- -> Retourne une erreur "'Impossible de supprimer un noeud ayant encore des fils non supprimés"
- execute objDelete 'SDEVIDAL', 1, 'REP'
- -> OK (réponse 1 flagée comme supprimée)
- execute objDelete 'SDEVIDAL', 2, 'REP'
- -> OK (réponse 2 flagée comme supprimée)
- execute objDelete 'SDEVIDAL', 1, 'ART'
- -> OK (article 1 flagé comme supprimé)
|
Mais c'est la dernière étape qui foire, c'est à dire le seul moment où je rentre dans mon curseur et que je tente l'appelle récursif...
D'après les conventions de nommage de SQL Server, mettre un "@" permet d'expliciter que j'utilise une variable locale. J'ai donc tenté d'en mettre un au nom de mon curseur, mais à ce moment j'obtiens une erreur à la compilation sur le "FOR" du "declare cursor @fils for select ..." donc j'en déduit que cette règle de nommage ne s'applique pas aux curseurs. |