Précédent   Forum des professionnels en informatique > Bases de données > Sybase
Sybase Forum sur la base de données Sybase. Avant de poster -> F.A.Q Sybase, Tutoriels Sybase
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 08/05/2006, 21h22   #1
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 92
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 92
Points : 33
Points : 33
Par défaut [ASE12][TSQL]Curseur sous Sybase

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
jeff37 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2006, 12h24   #2
Rédacteur/Modérateur
 
Inscription : janvier 2006
Messages : 1 301
Détails du profil
Informations personnelles :
Âge : 52

Informations forums :
Inscription : janvier 2006
Messages : 1 301
Points : 1 505
Points : 1 505
Envoyer un message via AIM à mpeppler
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:

Code :
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
Il y a quelques options supplémentaires qui sont bien décrites dans le manuel (p.ex. manuel de référence)

Michael
mpeppler est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/05/2006, 16h18   #3
Membre du Club
 
Inscription : octobre 2005
Messages : 79
Détails du profil
Informations personnelles :
Âge : 32

Informations forums :
Inscription : octobre 2005
Messages : 79
Points : 46
Points : 46
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 :
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
lsone est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/01/2007, 15h21   #4
Membre du Club
 
Inscription : décembre 2006
Messages : 47
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 47
Points : 41
Points : 41
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:

Citation:
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
j-Christo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/01/2007, 17h42   #5
Membre confirmé
 
Homme
Développeur informatique
Inscription : octobre 2006
Messages : 181
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : octobre 2006
Messages : 181
Points : 267
Points : 267
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.
Jean.Cri1 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 11h58.


 
 
 
 
Partenaires

Hébergement Web