Bonjour,
Je dois travailler sur Sybase ASE 12 que je connais très peu.
J'ai besoin d'utiliser un curseur mais il semble que la synthaxe soit différente du T-SQL de MS.
Qq'un pourrait il me donner des infos svp ?
Merci d'avance.
jeff
Bonjour,
Je dois travailler sur Sybase ASE 12 que je connais très peu.
J'ai besoin d'utiliser un curseur mais il semble que la synthaxe soit différente du T-SQL de MS.
Qq'un pourrait il me donner des infos svp ?
Merci d'avance.
jeff
Est-ce que c'est dans une proc stockée, ou dans un batch SQL normal?
Si c'est dans un batch normal il faut séparer la déclaration du curseur du reste. La séquence "normale" va comme ceci:
Il y a quelques options supplémentaires qui sont bien décrites dans le manuel (p.ex. manuel de référence)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 declare CURSORNAME cursor for SELECT ... FROM ... WHERE .... open CURSORNAME fetch CURSORNAME into @var1, @var2, ... while @@sqlstatus = 0 begin -- faire qqch avec les variables... fetch CURSORNAME into @var1, @var2, ... end close CURSORNAME deallocate cursor CURSORNAME
Michael
Rappel sur les curseurs :
Variables globales relatives aux curseurs
@@rowcount
- Après un fetch, contient le nombre de lignes renvoyées par des fetch depuis l'ouverture de ce curseur
- Après toute instruction DML (data manipulation langage : select, insert, update, delete), contient le nombre de lignes affectées par l'instruction
@@sqlstatus
- contient 0 si le dernier fetch a réussi
- contient 1 si le dernier fetch a rencontré une erreur
- contient 2 si le dernier fetch a échoué parce qu'il n'y a plus de ligne dans le curseur
Fermeture d'un curseur
ASE ferme automatiquement les curseurs quand :
- la session qui l'a créé est terminée.
- la procédure stockée qui l'a créé est terminée.
On peut réouvrir un curseur fermé (close cursor_name). Le pointeur du curseur revient au commencement du resultset.
On ne peut pas réouvrir un curseur désalloué (deallocate cursor_name) sans le recréer au préalable.
fetch : remarques complémentaires
fetch fait descendre toujours le pointeur jusqu'au resultset.
Il est impossible de faire remonter le pointeur dans le resultset.
La fermeture et la réouverture (open cursor_name & close cursor_name) fait revenir le pointeur au début.
Par défaut, fetch retourne toujours une ligne.
On peut utiliser l'option set cursor rows pour modifier ce positionnement.
Syntaxe : set cursor rows NUMBER for CURSOR_NAME
Exemple : set cursor rows 5 for CURSOR_NAME
Recommandations
Il faut :
- toujours spécifier le mode du curseur dans l'instruction declare,
- évitez de laisser les curseurs ouverts pendant une longue durée,
- si la même opération est effectuée pour toutes les lignes d'un curseur, n'utilisez pas de curseur.
Règles
La table sur laquelle un curseur for update est déclaré doit :
- avoir un index unique, ou
- utiliser un schéma de verrouillage DataPages ou Datarows
Les curseurs for update nécessitent un index unique sur des tables verrouillés Allpages pour permettre au curseur d'identifier chaque ligne d'une manière unique.
Les verrouillages Datapages et Datarows des tables sont utilisés pour déterminer les ID des lignes, et un curseur for update peut les utiliser pour identifier chaque ligne.
Exemple d'un curseur for update
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 -- Fonctionnement : -- Augmentez, de 50%, tous les prix inférieurs au prix moyen. -- Diminuez, de 25%, tous les prix supérieurs ou égaux au prix moyen. -- on déclare un curseur declare title_update cursor for select title_id, price from titles for update go -- on déclare des variables locale declare @avg_price money, @title_id int, @price money -- On ouvre le curseur open title_update -- On commence une transaction begin tran -- on calcule le prix moyen select @avg_price = avg(price) from titles holdlock -- on fait descendre le curseur tout en affectant les variables locales @title_id, @price fetch title_update into @title_id, @price -- Tant qu'il y a des lignes on boucle while @@sqlstatus <> 2 begin -- Gestion d'erreurs sur le curseur, si le dernier fetch a rencontré une erreur if @@sqlstatus = 1 begin -- Annule rollback tran -- Ecriture d'un message d'erreur raiserror 21001 "Fetch failed in cursor" -- Fermeture du curseur close title_update -- Désalloue le curseur deallocate cursor title_update -- On sort du batch return end -- Si le prix est inférieur à la moyenne if @price < @avg_price -- Augmente de 50% update titles set price = price * $1.50 where current of title_update -- sur la ligne courante du curseur else -- Diminue de 25% update titles set price = price * $.75 where current of title_update -- Gestion d'erreurs sur l'update ci-dessus if @@error <> 0 begin rollback tran raiserror 22001 "Update in cursor failed" close title_update deallocate cursor title_update return end -- On descend le pointeur fetch title_update into @title_id, @price end -- Fin du while -- Valide la transaction commit tran close title_update deallocate cursor title_update go -- fin du batch
bonjour je recherche une réponse à mon problème et il me semble que ce que vous avez expliqué pourrez m'y aider mais j'ai du mal à comprendre l'utilité du fetch
dans mon cas je suis en train de créer une fonction f1 qui reçoit un paramètre Document_ID
je dois parcourir une table Dat_document_line et lorsque l'un des champs a la même valeur que document_id, j'appel une fonction f2 en passant en paramètre une quantité et une référence
et je somme tous les résultats obtenus dans ma fonction f1 par somme=somme+resultat F2
donc comment est ce que je peux utiliser les fetch dans mon cas
pour info voilà ce que fait ma fonction f2:
ALTER FUNCTION "DBA"."fr_getProductPrice"( @Product_reference_id integer, @quantite integer)
RETURNS numeric (28,3)
DETERMINISTIC
BEGIN
DECLARE cout numeric (28,3);
declare prix numeric(28,3);
select Standard_price into prix
from Ref_Product_Reference
where Product_reference_id=@Product_reference_id;
set cout = (@quantite*prix);
RETURN cout;
END
Avec une fonction qui s'appelle fr_getProductPrice et qui retourne en fait le prix d'un produit multiplié par une quantité, ca sent l'usine à gaz cette histoire.
Essaie donc plutot de tout faire dans une seule requete avec des agrégats et eventuellement un compute.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager