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

MS SQL Server Discussion :

Un seul enregistrement ?


Sujet :

MS SQL Server

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 7
    Points : 1
    Points
    1
    Par défaut Un seul enregistrement ?
    Bonjour,
    Après quelques recherches dans la FAQ et le forum, je ne trouve pas spécialement de réponse à ma question.
    Tout d'abord Je ne suis pas un grand spécialiste de SQL, mais j'essaie de m'adapter.

    Les faits :
    Pour l'instant c'est l'étude rien a été fait.
    Je vais avoir besoin dans une base (à ma disposition SQL SERVER 7 ou 2000) d'afficher chaque enregistrement d'une table et d'enregistrer les modifications. Tous les enregistrements vont devoir être traités.
    Plusieurs utilisateurs (une petite dizaine) vont avoir chaque enregistrement remonter automatiquement (php ou asp)
    J'envisageais de mettre un statut sur chaque enregistrement (du style a traiter,traité) mais comment s'assurer que 1 utilisateur n'aura pas le même enregistrement qu'un autre.
    Je pensais tout d'abord lors du SELECT (sur le 1er élément "à traiter" faire un UPDATE pour passer son statut "en cours") mais j'ai peur que le temps de faire la modification sur le statut "en cours", ce même enregistrement remonte pour 1 autre utilisateur.

    Ne sachant comment aborder ce problème de façon sécurisé je me tourne vers vous afin de m'orienter.

    Merci par avance.

    NicoDD.

  2. #2
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 711
    Points : 4 796
    Points
    4 796
    Par défaut
    Lors d'une "demande pour un enregistrement" de l'application,
    tu peux envoyer à SQL Server le nom d'utilisateur (qu'on suppose unique !) de l'application.
    En plus d'une colonne "statut", tu peux ajouter une colonne "Attribution" et y placer le nom de l'utilisateur ayant "réclamé" un enregistrement.
    récupération :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM maTable WHERE Status = 'en cours' AND Attribution = 'Wladimir'
    Cela permettra de savoir aussi qui a fait quoi comme traitement.

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Merci pour ta réponse....
    Donc si j'ai bien compris :

    1: je fait un SELECT sur le premier enregistrement disponible (statut en cours) puis fait un UPDATE de attribution (qui sera sans données au départ) avec pour données le nom unique de l'utilisateur.

    2. je récupère cet enregistrement et l'affiche à l'utilisateur concerné.

    Si échec en 2. car un autre utilisateur a fait une demande attribution en même temps sur le même enregistrement je recommence 1.

    Ai-je bien tout compris ?

    Merci.

  4. #4
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 711
    Points : 4 796
    Points
    4 796
    Par défaut
    Il n'y aura pas d'échec ...

    Il faut utiliser la baguette magique de la transaction

  5. #5
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Il n'y aura pas d'échec ...

    Il faut utiliser la baguette magique de la transaction
    J'ai peur de ne pas être le Harry Potter de la Transaction....

    Si tu peux m'éclairer.....


    Merci.

    Nico

  6. #6
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 711
    Points : 4 796
    Points
    4 796
    Par défaut
    C'est probablement encore plus simple.
    On suppose que chaque enregistrement est numéroté par un compteur (clé primaire recommandée).
    Donc une application cliente va envoyer directement la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE maTable SET Statut = 'en cours', Attritution = 'Hector' 
    WHERE Compteur = (SELECT MIN(Compteur) 
    FROM maTable WHERE Statut = 'à traiter')
    Comme on fait la manoeuvre en une seule instruction, on n'a pas vraiment besoin de transaction

    Après, on fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT * FROM maTable 
    WHERE Statut = 'en cours' AND Attritution = 'Hector'
    Sinon, pour être "ceinture et bretelles" avec une transaction, cela donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    BEGIN TRANSACTION
    UPDATE maTable SET Statut = 'en cours', Attritution = 'Hector' 
    WHERE Compteur = (SELECT MIN(Compteur) FROM maTable WHERE Statut = 'à traiter')
    SELECT * FROM maTable 
    WHERE Statut = 'en cours' AND Attritution = 'Hector'
    COMMIT
    Si quelque chose foire au milieu, la base se remet dans son état d'avant la transaction

  7. #7
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Merci....



  8. #8
    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

    Sinon vous pouvez utiliser la clause OUTPUT, pour mettre à jour les lignes et récuperer les lignes mises a jour en une seule reuqte :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    UPDATE MaTable
    SET Statut = 'en cours'
    OUTPUT INSERTED.*
    WHERE Statut <> 'en cours'
    AND...

    Vous pourriez alors vous passer de la colonne Attribution

    Par contre, pensez peut être à mettre en place un mécanisme afin que si un utilisateur commence a mettre a jour, part prendre un café, se casse la jambe à la cafet et ne valide jamais ses modifications, le statut revienne à 'à traiter' au bout d'un moment...

  9. #9
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 711
    Points : 4 796
    Points
    4 796
    Par défaut
    la clause OUTPUT ...
    on est sur du SQL server 7 ou 2000.
    OUTPUT n'existe pas encore

  10. #10
    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
    oups

    j'avais raté ce détail en effet...

  11. #11
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Merci pour vos remarques complémentaires.....

    J'ai effectivement prévu un mécanisme pour remettre le statut "A traiter".....
    Pour éviter qu'il se casse la jambe, j'interdirais le café....
    Merci encore

  12. #12
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Encore une petite question :
    puis-je récupérer les champs de l'enregistrement que je viens de modifier avec cette seule requete ou dois je passer par un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT id,nom, prenom FROM maTable WHERE attribution ='hector' AND statut='en cours'.
    Car quand j'essai de récuperer l'ID j'ai une erreur :
    Impossible de trouver l'objet dans la collection correspondant au nom ou à la référence ordinale demandé.
    Merci par avance.

  13. #13
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 711
    Points : 4 796
    Points
    4 796
    Par défaut
    Le message d'erreur est un peu étrange.
    Peux-tu poster la vraie structure de la table avec la vraie requête SELECT ... ?

  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
    je pense que ce message d'erreur vient de son application et n'est pas en rapport avec une requete, mais avec une mauvaise utilisation des classes qu'il utilise pour discuter avec la BDD

    et pour répondre à la question, oui, tu dois refaire un SELECT. En fait la clause OUTPUT aurait pu te permettre de récupérer les lignes mises à jour par la commande UPDATE, mais comme l'a fait remarquer Népomucène, ta version de SQL server est trop ancienne...

  15. #15
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Aperçu de la Structure de la Table :
    sId (int) - auto increment
    sNom - varchar
    sAttribution - varchar
    sStatut (valeur défaut "à traiter")
    Requete :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE maTable SET sStatut = 'en cours', sAttritution = 'Hector' 
    WHERE sId = (SELECT MIN(sId) 
    FROM maTable WHERE sStatut = 'à traiter'
    Le résultat attendu est bien là. Le premier enregistrement passe bien à En cours et avec le champ attribution correctement renseigné

    Si j'essai via asp d'accéder à sID j'ai le message cité plus haut :
    Impossible de trouver l'objet dans la collection correspondant au nom ou à la référence ordinale demandé.
    J'ai également essayer de modifier comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE maTable SET sStatut = 'en cours', sAttritution = 'Hector' 
    WHERE sId = (SELECT MIN(sId),sId 
    FROM maTable WHERE sStatut = 'à traiter'
    et là cela me retounre une erreur concernant ma sous requete car elle ne contient pas EXIST (de tête car je ne suis pas avec l'environnement de DEV)

    Mais bon si :
    et pour répondre à la question, oui, tu dois refaire un SELECT. En fait la clause OUTPUT aurait pu te permettre de récupérer les lignes mises à jour par la commande UPDATE, mais comme l'a fait remarquer Népomucène, ta version de SQL server est trop ancienne...
    je vais passer par un nv SELECT.


    Merci

  16. #16
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 711
    Points : 4 796
    Points
    4 796
    Par défaut
    je vais passer par un nv SELECT
    Avec cette version de SQL Server, il faut faire 2 requêtes
    La 1ère pour l'UPDATE
    la 2ème avec SELECT

    Dans le code que tu postes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE maTable SET sStatut = 'en cours', sAttritution = 'Hector' 
    WHERE sId = (SELECT MIN(sId) 
    FROM maTable WHERE sStatut = 'à traiter'
    Il manque une parenthèse à la fin. C'est peut-être un oubli de copier/coller

    par ailleurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE maTable SET sStatut = 'en cours', sAttritution = 'Hector' 
    WHERE sId = (SELECT MIN(sId),sId 
    FROM maTable WHERE sStatut = 'à traiter'
    ... ne peut pas fonctionner car la clause "WHERE sId =" attend une seule valeur.
    Or, ta requête "SELECT MIN(sId),sId FROM maTable" renvoie plusieurs valeur (en plus, il y a un problème de GROUP BY!).
    C'est peut-être l'origine du message d'erreur précédent

  17. #17
    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 n'avais pas fait gaffe que tu ne prenais qu'une ligne à chaque fois.( MIN() )
    Il y a peut etre une solution plus simple, tu peux effectivement faire un update et récuperer les valeurs en même temps :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    DECLARE @sID INT
    DECLARE @sNom VARCHAR(?)
     
    UPDATE MaTable
    SET sAttribution = 'toto',
    sStatut = 'en cours',
    @sID = sId,
    @sNom = sNom
    WHERE sId = (SELECT MIN(sId) FROM MaTable WHERE sStatut = 'à traiter')

    et tu mets ca dans une procédure stockée avec les parametres @sID et @sNom en OUTPUT, que tu récupère dans ton appli.

  18. #18
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 711
    Points : 4 796
    Points
    4 796
    Par défaut
    Je ne suis pas un grand spécialiste de SQL
    nous dit NicoDD.
    J'ai préféré ne pas l'embarquer dans une procédure stockée,
    qui est certes toujours préférable, mais beaucoup moins accessible au débutant
    (surtout avec des paramètres OUTPUT)

  19. #19
    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
    C'est l'occasion d'apprendre

    les parametres output, c'est juste un mot a rajouter ! et en plus c'est facile, ce mot, c'est OUTPUT

    Bon cela dit c'est vrai que pour l'appeler depuis son appli, ca risque de changer la méthode... mais il a dit qu'il était débutant en SQL, pas en php ou asp... et des exemples pour faire çà, ça se trouve facilement...

    bref, sinon, il y a toujours moyen de faire un
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT @sId AS sId, @sNom as sNom

    Après l'UPDATE

  20. #20
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    J'ai préféré ne pas l'embarquer dans une procédure stockée,
    qui est certes toujours préférable, mais beaucoup moins accessible au débutant
    (surtout avec des paramètres OUTPUT)
    Notre ami passe surement par ADO pour exécuter cette requete?

    Impossible de trouver l'objet dans la collection correspondant au nom ou à la référence ordinale demandé.
    -> Ça c'est une erreur ADO surement lors d'un GetOrdinal() fais sur un SqlDataReader...

    Si c'est le cas rien de plus facile en mettant ceci en CommandText devotre Sqlcommand:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    "DECLARE @sID INT
     
    UPDATE MaTable
    SET sAttribution = 'toto',
    sStatut = 'en cours',
    @sID = sId,
    WHERE sId = (SELECT MIN(sId) FROM MaTable WHERE sStatut = 'à traiter');SELECT @sID"
    Puis récupérer @sID en faisant un ExecuteScalar()

Discussions similaires

  1. Sous-formulaire avec 1 seul enregistrement
    Par Farbin dans le forum Access
    Réponses: 6
    Dernier message: 08/08/2006, 16h37
  2. [Access 2003]Comment obtenir un seul enregistrement?
    Par steeves5 dans le forum Access
    Réponses: 19
    Dernier message: 28/04/2006, 12h05
  3. Réponses: 1
    Dernier message: 26/04/2006, 09h52
  4. Voir un seul enregistrement
    Par PrinceMaster77 dans le forum SQL
    Réponses: 1
    Dernier message: 15/11/2004, 16h51
  5. ROLLBACK sur une seul enregistrement
    Par toctoc80 dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 30/04/2004, 20h22

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