IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Utilisation d'un curseur pour changer les données


Sujet :

Langage SQL

  1. #1
    Membre confirmé Avatar de Julien698
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2013
    Messages : 237
    Points : 473
    Points
    473
    Par défaut Utilisation d'un curseur pour changer les données
    Bonjour,

    Je souhaite affecter de nouvelles valeurs dans les champs d'une colonne, une boucle for each m'aurait convenue mais malheureusement comme vous le savez elle n'existe pas en SQL. C'est pourquoi que je souhaite m'orienter vers un curseur, n'ayant pas réussi avec un WHILE.
    Voici la table sur laquelle je travaille
        ID      |    TYPE   |    RANK
    CPVFFF00001 |     24    |     5
    DOTFFF0002  |     24    |     1
    DOXFF78000  |     24    |     9
    XXLFRRF500  |     24    |     8
    PSRRFGTF00  |     24    |     7
    Voilà, l'idée est que la colonne RANK devienne une suite incrémentée de 1 en commençant par 1, en l’occurrence 1,2,3,4,5 pour ce cas ci. C'est essentiel pour que mon code en C# qui agit sur cette table fonctionne. Je compte faire ce cette requête une procédure stockée qui sera appelée au lancement de mon programme C# pour être toujours sur d'avoir 1,3,3,4,5 pour la colonne RANK.
    Voici une requête que j'ai essayée mais elle ne marche pas ! Elle ne me met que des 5 pour cette table.

    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
    DECLARE @numeroligne INT
    SET @numeroligne = 1
    DECLARE @lignemax INT
    SET @lignemax = 5
     
    DECLARE curseur_rank CURSOR FOR
    SELECT RANK FROM dbo.lesrank
    WHERE lestype='24'
    OPEN curseur_rank
    FETCH  curseur_rank
    WHILE(@numeroligne <= @lignemax)
    BEGIN
    UPDATE dbo.lesrank
    SET RANK = @numeroligne
    SET @numeroligne=@numeroligne+1
    FETCH NEXT FROM curseur_rank
    end
    Si vous avez d'autre solutions différentes que celle du curseur je suis aussi preneur !

    Merci d'avance

    Julien

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 803
    Points
    30 803
    Par défaut
    Sur quel critère souhaites tu ordonner ton RANK ?
    Une table n'est pas ordonnée par défaut et la même requête est susceptible de retourner les lignes dans un ordre différent si elle ne comporte pas de clause ORDER BY.

    Quand tu exécutes UPDATE dbo.lesrank SET RANK = @numeroligne, tu appliques la même mise à jour sur toutes les lignes de la table. Je ne suis pas certain que c'est ce que tu recherches
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Membre confirmé Avatar de Julien698
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2013
    Messages : 237
    Points : 473
    Points
    473
    Par défaut
    Je souhaite ordonner RANK dans l'ordre croissant. Donc ORDER BY [RANK] ASC. Je ne souhaite pas appliquer la même mise à jour sur tout les lignes. Au contraire chaque ligne doit avoir une mise à jour différente, par exemple pour la première ligne RANK sera mis à jour par 1, pour la deuxième ligne RANK sera mis à jour à 2 et ainsi de suite, c'est pour ça je j'incrémente la variable @numeroligne à chaque passage dans la boucle While.
    Après j'ai également vu qu'il y avait la fonction ROW_NUMBER() qui existait, et qui pouvait peut-être m'aider dans ma situation en faisant SET [RANK] = ROW_NUMBER(...)
    cdt,

    Julien

  4. #4
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 803
    Points
    30 803
    Par défaut
    Tout simplement comme ça, un curseur est inutile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE  dbo.lesrank tbl 
    SET     tbl.rank = ROW_NUMBER() OVER (ORDER BY tbl.rank)
    ;
    Attention, RANK est un mot réservé du langage SQL et ne doit pas être utilisé pour nommer un objet de la base de données (colonne, table...)
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  5. #5
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Et si la requête de al1_24 ne fonctionne pas avec la fonction fenêtrée dans le SET, on peut contourner ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    WITH CTE AS(
        SELECT rank, ROW_NUMBER() OVER (ORDER BY tbl.rank) AS rn
        FROM dbo.lesrank 
    )
    UPDATE CTE
    SET rank = rn

  6. #6
    Membre confirmé Avatar de Julien698
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2013
    Messages : 237
    Points : 473
    Points
    473
    Par défaut
    Citation Envoyé par al1_24 Voir le message
    Tout simplement comme ça, un curseur est inutile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE  dbo.lesrank tbl 
    SET     tbl.rank = ROW_NUMBER() OVER (ORDER BY tbl.rank)
    ;
    Attention, RANK est un mot réservé du langage SQL et ne doit pas être utilisé pour nommer un objet de la base de données (colonne, table...)

    Je suis sous SQL Server 2008 et malheureusement UPDATE ne prend pas ROW_NUMBER() OVER (ORDER BY tbl.rank)Il me dit que ce code doit être inséré dans les clauses ORDER BY ou SELECTSinon j'ai essayé de passer par une table temporaire :

    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
    DECLARE @tmp TABLE
    	(
    		Ranking INT,
    		ShopIdd VARCHAR(50)
    	);
     
    --DECLARE TABLE @tmp (Ranking INT, ShopIdd VARCHAR(50))
     
    INSERT INTO @tmp
    	SELECT ROW_NUMBER() OVER (ORDER BY RANK), ShopId FROM LesRank
     
    DECLARE @RankingBis INT
    SET @RankingBis  = 1
     
    UPDATE  dbo.LesRank 
    SET     [RANK] = @RankingBis
    WHERE EXISTS(SELECT @RankingBis = MAX(Ranking) 
    FROM @tmp t WHERE t.ShopIdd = ShopId)
    Mais sans succès il n'aime pas le égal ici WHERE EXISTS(SELECT @RankingBis = MAX(Ranking).


    Je vais réessayer d'utiliser le curseur.

    cdt,

    Julien

  7. #7
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par Julien698 Voir le message
    Il me dit que ce code doit être inséré dans les clauses ORDER BY ou SELECT
    Faites comme je vous ai proposé !

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 198
    Points : 12 774
    Points
    12 774
    Par défaut
    J'ai une petite question, peut-être idiote: à quoi bon renuméroter les lignes ?
    Si la colonne rank ne sert qu'à ordonner les lignes dans le résultat de la requête, et qu'elles sont identifiées par ID, il suffit que la requête renvoie rowno en lieu et place de Rank, et le programme en C# n'y voit que du feux:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    select id,type,rowno
    from LaTable
    order by LaTable.rank

    Ou alors j'ai raté quelque chose ?

    Tatayo.

  9. #9
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Je me posais la même question.

    Cela dit, si Julien698 veut récupérer une seule ligne par son ID et connaitre son rang global dans la table, ça pourra éviter un scan complet...

    Mais il faudrait connaitre le contexte global, car en effet, cela cache peut être un problème de conception...

  10. #10
    Membre confirmé Avatar de Julien698
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2013
    Messages : 237
    Points : 473
    Points
    473
    Par défaut
    Bonjour tout le monde,

    J'ai enfin trouvé la solution pour mon problème, en utilisant un curseur. Je poste le code si jamais il peut aider quelqu'un qui se trouve dans la même situation.

    Merci pour vos réponses !



    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
    DECLARE @i int
    SET @i = 1
    DECLARE CURSEUR CURSOR FOR
    SELECT rank FROM dbo.lesrank WHERE shoptype ='136' FOR UPDATE OF rank 
    OPEN Curseur
    FETCH NEXT FROM CURSEUR
    WHILE @@FETCH_STATUS = 0
    	BEGIN
    		print @i
    	  UPDATE dbo.lesrank
    	  SET    rank=@i
    	  WHERE  CURRENT OF CURSEUR	
    	  SET @i = @i + 1
    	FETCH NEXT FROM CURSEUR
    	END;
    CLOSE CURSEUR;
    DEALLOCATE CURSEUR;
    GO

  11. #11
    Membre confirmé Avatar de Julien698
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2013
    Messages : 237
    Points : 473
    Points
    473
    Par défaut
    Pour vous répondre, j'ai besoin de la colonne "rank" car mon programme la modifie. Il s'agit en fait d'une interface ou on peut déplacer les icônes, le "rank" défini sa position. Mon programme C# agit sur les ligne en décrémentant la ligne du bas de 1 et incrémentant la ligne du haut de 1 pour pouvoir les permuter. Seulement dans la base il y avait un soucis, c'est que les "ranks" ne se suivaient pas par exemple j'avais 7,8,12, et si je voulais permuter les lignes qui avaient comme rank 8 et 12 ça ne pouvait pas marcher, avec le système d'incrément j'aurais eu 9 et 11 et donc aucune modification.
    Grâce à cette requête qui sera dans une procédure stockée qui sera appelée au lancement du programme je n'aurai plus de soucis ! De même les icônes peuvent être supprimé et un null peut apparaître, c'est pourquoi elle est nécessaire.

    Merci de votre aide

    cdt,

    Julien

  12. #12
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 803
    Points
    30 803
    Par défaut
    Ton curseur étant défini sans clause ORDER BY, cela signifie que tu laisses le SGBD choisir, à chaque exécution de la procédure, la valeur qui sera enregistrée dans la colonne RANK sans aucune assurance que ce soit à chaque fois la même. Une seule certitude : cette valeur sera unique et comprise entre 1 et le nombre de lignes retourné par la requête.
    C'est un choix..
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  13. #13
    Membre confirmé Avatar de Julien698
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2013
    Messages : 237
    Points : 473
    Points
    473
    Par défaut
    Citation Envoyé par al1_24 Voir le message
    Ton curseur étant défini sans clause ORDER BY, cela signifie que tu laisses le SGBD choisir, à chaque exécution de la procédure, la valeur qui sera enregistrée dans la colonne RANK sans aucune assurance que ce soit à chaque fois la même. Une seule certitude : cette valeur sera unique et comprise entre 1 et le nombre de lignes retourné par la requête.
    C'est un choix..
    Mince, je savais pas !
    Tu veux dire qu'il faut faire quelque chose comme ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    DECLARE CURSEUR CURSOR FOR
    SELECT [rank] FROM dbo.lesrank WHERE shoptype ='136' ORDER BY [rank]--FOR UPDATE OF [rank] 
    OPEN Curseur

  14. #14
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Et la solution que je vous avais proposée (qui n'est ni plus ni moins qu'une adaptation de la requête al1_24 pour éviter le problème que vous avez rencontré) tiens en 6 lignes, et est ensembliste...

    l'avez-vous testée ?

  15. #15
    Membre confirmé Avatar de Julien698
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2013
    Messages : 237
    Points : 473
    Points
    473
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Et la solution que je vous avais proposée (qui n'est ni plus ni moins qu'une adaptation de la requête al1_24 pour éviter le problème que vous avez rencontré) tiens en 6 lignes, et est ensembliste...

    l'avez-vous testée ?

    Oui bien sur, je l'ai essayée mais malheureusement je reçois un message d'erreur :
    Msg*4104, Niveau*16, État*1, Ligne*1
    L'identificateur en plusieurs parties 'tbl.rank' ne peut pas être lié.

  16. #16
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par Julien698 Voir le message
    Oui bien sur, je l'ai essayée mais malheureusement je reçois un message d'erreur :
    Msg*4104, Niveau*16, État*1, Ligne*1
    L'identificateur en plusieurs parties 'tbl.rank' ne peut pas être lié.
    en effet !

    enlevez simplement l'alias que j'ai laissé par erreur dans la CTE :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    WITH CTE AS(
        SELECT rank, ROW_NUMBER() OVER (ORDER BY rank) AS rn
        FROM dbo.lesrank 
    )
    UPDATE CTE
    SET rank = rn

  17. #17
    Membre confirmé Avatar de Julien698
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2013
    Messages : 237
    Points : 473
    Points
    473
    Par défaut
    Cette requête fonctionne aussi comme je le souhaite, je vais retenir cette là étant donné qu'elle est moins lourde que celle du curseur !

    Merci beaucoup !

    Cordialement

    Julien

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. recherche dans une colonne pour changer les données
    Par cimbra55 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 26/03/2009, 16h49
  2. Réponses: 2
    Dernier message: 26/05/2008, 16h26
  3. Réponses: 7
    Dernier message: 14/02/2008, 12h22
  4. Quel pattern utiliser pour changer les possibilités d'un objet
    Par lichman dans le forum Design Patterns
    Réponses: 4
    Dernier message: 05/10/2007, 14h02
  5. [SAX] Utilisation de LexicalHandler pour gérer les données CDATA en base 64
    Par tdeco dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 23/08/2007, 21h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo