Conception Et Réalisation (SQL Server) by Grare Stéphane - HTML preview

PLEASE NOTE: This is an HTML preview only and some elements such as links or page numbers may be incorrect.
Download the book in PDF, ePub, Kindle for a complete version.

Les curseurs

Le curseur est un mécanisme de mise en mémoire en tampon permettant de parcourir les

lignes d'enregistrements du résultat renvoyé par une requête. Les curseurs sont envoyés par

MS-SQL Server tout le temps, mais on ne voit pas le mécanisme se passer, ainsi lors d'une

requête SELECT, SQL Server va employer des curseurs.

Pour utiliser un curseur, il faut commencer par le déclarer :

DECLARE name CURSOR FOR

SELECT …

On peut aussi l'utiliser avec de la modification en ajoutant FOR UPDATE à la fin de la

requête, bien que ce ne soit pas conseillé.

Ensuite, il faut ouvrir ce curseur avec OPEN name et ne pas oublier de le fermer à la fin avec

CLOSE name. Il faut aussi utiliser DEALLOCATE pour libérer la mémoire du curseur.

Pour récupérer les valeurs actuelles contenues dans le curseur, il faut employer :

FETCH name INTO @value1, @value2 …

Cela va stocker les valeurs actuelles de l'enregistrement courant dans les variables @valueX,

qu'il ne faut surtout pas oublier de déclarer.

On peut néanmoins utiliser FETCH pour d'autres choses :

176

index-177_1.png

• Aller à la première ligne : FETCH FIRST FROM curseur_nom

• Aller à la dernière ligne : FETCH LAST FROM curseur_nom

• Aller à la ligne suivante : FETCH NEXT FROM curseur_nom

• Aller à la ligne précédente : FETCH PRIOR FROM curseur_nom

• Aller à la ligne X : FETCH ABSOLUTE ligne FROM curseur_nom

• Aller à X lignes plus loin que l'actuelle : FETCH RELATIVE ligne FROM curseur_nom

Pour parcourir un curseur, on peut employer une boucle WHILE qui teste la valeur de la

fonction @@FETCH_STATUS qui renvoie 0 tant que l'on n'est pas à la fin.

DECLARE @numfou VARCHAR(50)

DECLARE curseur_comparfou CURSOR FOR

SELECT OBSCOM FROM vente.ENTCOM

OPEN curseur_comparfou

FETCH curseur_comparfou INTO @numfou

WHILE @@FETCH_STATUS = 0

BEGIN

PRINT @numfou

FETCH curseur_comparfou INTO @numfou

END

CLOSE curseur_comparfou

DEALLOCATE curseur_comparfou

Ici, nous récupérons toutes les observations de la colonne OBSCOM de la table ENTCOM.

Modifions l’exemple précèdent de façon à l’incorporé dans une procédure stockée et de nous

donner les observations d’un fournisseur précis.

CREATE PROCEDURE recherche_ligne_com

-- On déclare nos variables

@numfou VARCHAR(50)

AS

BEGIN

-- On désigne curseur_comparfou

DECLARE curseur_comparfou CURSOR FOR

-- Le curseur agi pour la sélection suivante

SELECT OBSCOM FROM vente.ENTCOM WHERE NUMFOU = @numfou

-- On ouvre le curseur

OPEN curseur_comparfou

FETCH curseur_comparfou INTO @numfou

WHILE @@FETCH_STATUS = 0

BEGIN

PRINT @numfou

FETCH curseur_comparfou INTO @numfou

177

index-178_1.png

END

-- On ferme le curseur

CLOSE curseur_comparfou

-- On le vide de la mémoire

DEALLOCATE curseur_comparfou

END

GO

On interroge notre procédure stockée :

EXEC recherche_ligne_com3 '120'

On peut bien entendu imbriquer plusieurs curseurs les uns dans les autres pour des choses

plus compliquées.

Concrètement, maintenant que nous avons vu comment fonctionnait un curseur et comment

l'employer, que fait-il de plus qu'une simple requête ? Il permet surtout d'intervenir sur le

résultat de la requête. On peut intervenir sur chaque valeur retournée, on peut modifier ces

valeurs ou supprimer des lignes. On peut aussi réaliser des opérations avec ces données

avant qu'elles arrivent au programme qui les utilise, c'est à dire des calculs de somme, des

maximums, des modifications de date, des formatages de chaînes de caractères.

Un exemple intéressant est le parcours avec rupture, c'est à dire parcourir et si on a déjà eu

une fois cet objet on ne le réaffiche pas. Dans l'exemple que je vais vous présenter, on affiche

tous les genres, les acteurs par genre et pour chaque acteur les livres qu'ils ont écrits. On

emploie des ruptures pour vérifier que l'on n'a pas déjà affiché une fois cet élément :

DECLARE @titre VARCHAR(50), @genre VARCHAR(50), @rupture_genre VARCHAR(50),

@rupture_auteur VARCHAR(50), @auteur VARCHAR(50)

DECLARE @i_genre INT

SET @i_genre = 1

SET @rupture_genre = ''

SET @rupture_auteur = ''

DECLARE curseur_ouvrages CURSOR FOR

SELECT ouvrage_titre, genre_nom, auteur_nom FROM t_ouvrages O

LEFT OUTER JOIN t_genres

ON genre_id = ouvrage_genre

LEFT OUTER JOIN t_ouvrages_auteurs TOA

ON TOA.ouvrage_id = O.ouvrage_id

LEFT OUTER JOIN t_auteurs TA

ON TA.auteur_id = TOA.auteur_id

ORDER BY ouvrage_genre

OPEN curseur_ouvrages

FETCH curseur_ouvrages INTO @titre , @genre, @auteur

WHILE @@FETCH_STATUS = 0

BEGIN

178

IF @genre != @rupture_genre

BEGIN

PRINT ''

PRINT CONVERT(CHAR(2),@i_genre) + '. ' + @genre

SET @i_genre = @i_genre + 1

SET @rupture_auteur = ''

END

IF @auteur != @rupture_auteur

BEGIN

PRINT ''

PRINT @auteur

PRINT '------------'

END

PRINT @titre;

SET @rupture_genre = @genre

SET @rupture_auteur = @auteur

FETCH curseur_ouvrages INTO @titre , @genre, @auteur

END

CLOSE curseur_ouvrages

DEALLOCATE curseur_ouvrages