Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server
MS SQL-Server Forum Microsoft SQL-Server. Avant de poster -> FAQ SQL-Server, Tutoriels SQL-Server
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 28/03/2011, 21h40   #1
Invité de passage
 
Inscription : mars 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 7
Points : 0
Points : 0
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.
NicoDD. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/03/2011, 22h15   #2
Membre Expert
 
Homme
Développeur java, access, sql server
Inscription : octobre 2005
Messages : 851
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 : 851
Points : 1 302
Points : 1 302
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 :
SELECT * FROM maTable WHERE STATUS = 'en cours' AND Attribution = 'Wladimir'
Cela permettra de savoir aussi qui a fait quoi comme traitement.
__________________
D'abord qu'il marche. Ensuite qu'il soit rapide. Enfin qu'il soit agréable à utiliser.
First, make it work. Then, make it fast. Finally, make it user-friendly.
Erst, mach', dass es funktioniert. Dann, mach', dass es schnell geht, Zum Schluss mach' es benutzerfreundlich.
Népomucène est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/03/2011, 22h24   #3
Invité de passage
 
Inscription : mars 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 7
Points : 0
Points : 0
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.
NicoDD. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/03/2011, 22h27   #4
Membre Expert
 
Homme
Développeur java, access, sql server
Inscription : octobre 2005
Messages : 851
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 : 851
Points : 1 302
Points : 1 302
Il n'y aura pas d'échec ...

Il faut utiliser la baguette magique de la transaction
__________________
D'abord qu'il marche. Ensuite qu'il soit rapide. Enfin qu'il soit agréable à utiliser.
First, make it work. Then, make it fast. Finally, make it user-friendly.
Erst, mach', dass es funktioniert. Dann, mach', dass es schnell geht, Zum Schluss mach' es benutzerfreundlich.
Népomucène est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/03/2011, 22h29   #5
Invité de passage
 
Inscription : mars 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 7
Points : 0
Points : 0
Citation:
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
NicoDD. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/03/2011, 22h39   #6
Membre Expert
 
Homme
Développeur java, access, sql server
Inscription : octobre 2005
Messages : 851
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 : 851
Points : 1 302
Points : 1 302
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 :
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 :
1
2
SELECT * FROM maTable 
WHERE Statut = 'en cours' AND Attritution = 'Hector'
Sinon, pour être "ceinture et bretelles" avec une transaction, cela donne :
Code :
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
__________________
D'abord qu'il marche. Ensuite qu'il soit rapide. Enfin qu'il soit agréable à utiliser.
First, make it work. Then, make it fast. Finally, make it user-friendly.
Erst, mach', dass es funktioniert. Dann, mach', dass es schnell geht, Zum Schluss mach' es benutzerfreundlich.
Népomucène est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/03/2011, 22h42   #7
Invité de passage
 
Inscription : mars 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 7
Points : 0
Points : 0
Merci....


NicoDD. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/03/2011, 13h21   #8
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
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 :
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...
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/03/2011, 15h49   #9
Membre Expert
 
Homme
Développeur java, access, sql server
Inscription : octobre 2005
Messages : 851
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 : 851
Points : 1 302
Points : 1 302
Citation:
la clause OUTPUT ...
on est sur du SQL server 7 ou 2000.
OUTPUT n'existe pas encore
__________________
D'abord qu'il marche. Ensuite qu'il soit rapide. Enfin qu'il soit agréable à utiliser.
First, make it work. Then, make it fast. Finally, make it user-friendly.
Erst, mach', dass es funktioniert. Dann, mach', dass es schnell geht, Zum Schluss mach' es benutzerfreundlich.
Népomucène est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/03/2011, 15h54   #10
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
oups

j'avais raté ce détail en effet...
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 08h55   #11
Invité de passage
 
Inscription : mars 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 7
Points : 0
Points : 0
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
NicoDD. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 13h34   #12
Invité de passage
 
Inscription : mars 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 7
Points : 0
Points : 0
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 :
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 :
Citation:
Impossible de trouver l'objet dans la collection correspondant au nom ou à la référence ordinale demandé.
Merci par avance.
NicoDD. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 13h39   #13
Membre Expert
 
Homme
Développeur java, access, sql server
Inscription : octobre 2005
Messages : 851
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 : 851
Points : 1 302
Points : 1 302
Le message d'erreur est un peu étrange.
Peux-tu poster la vraie structure de la table avec la vraie requête SELECT ... ?
__________________
D'abord qu'il marche. Ensuite qu'il soit rapide. Enfin qu'il soit agréable à utiliser.
First, make it work. Then, make it fast. Finally, make it user-friendly.
Erst, mach', dass es funktioniert. Dann, mach', dass es schnell geht, Zum Schluss mach' es benutzerfreundlich.
Népomucène est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 13h54   #14
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
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...
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 14h30   #15
Invité de passage
 
Inscription : mars 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 7
Points : 0
Points : 0
Aperçu de la Structure de la Table :
Citation:
sId (int) - auto increment
sNom - varchar
sAttribution - varchar
sStatut (valeur défaut "à traiter")
Requete :
Code :
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 :
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 :
Citation:
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
NicoDD. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 15h13   #16
Membre Expert
 
Homme
Développeur java, access, sql server
Inscription : octobre 2005
Messages : 851
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 : 851
Points : 1 302
Points : 1 302
Citation:
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 :
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 :
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
__________________
D'abord qu'il marche. Ensuite qu'il soit rapide. Enfin qu'il soit agréable à utiliser.
First, make it work. Then, make it fast. Finally, make it user-friendly.
Erst, mach', dass es funktioniert. Dann, mach', dass es schnell geht, Zum Schluss mach' es benutzerfreundlich.
Népomucène est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 15h19   #17
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
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 :
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.
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 15h32   #18
Membre Expert
 
Homme
Développeur java, access, sql server
Inscription : octobre 2005
Messages : 851
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 : 851
Points : 1 302
Points : 1 302
Citation:
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)
__________________
D'abord qu'il marche. Ensuite qu'il soit rapide. Enfin qu'il soit agréable à utiliser.
First, make it work. Then, make it fast. Finally, make it user-friendly.
Erst, mach', dass es funktioniert. Dann, mach', dass es schnell geht, Zum Schluss mach' es benutzerfreundlich.
Népomucène est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 15h42   #19
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
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 :
1
2
 
SELECT @sId AS sId, @sNom AS sNom

Après l'UPDATE
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/03/2011, 15h46   #20
Membre Expert
 
Avatar de iberserk
 
Homme Bruno IGNACE
Architecte de base de données
Inscription : novembre 2004
Messages : 1 299
Détails du profil
Informations personnelles :
Nom : Homme Bruno IGNACE
Âge : 30
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 299
Points : 2 282
Points : 2 282
Envoyer un message via MSN à iberserk
Citation:
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?

Citation:
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 :
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()
__________________
Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
iberserk 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 00h01.


 
 
 
 
Partenaires

Hébergement Web