2010-04-16 5 views
1

comment puis-je faire une «sélection pour la mise à jour», puis «mettre à jour» la ligne en utilisant ruby ​​oci8.sélectionner pour la mise à jour avec ruby ​​oci8

J'ai deux champs counter1 et counter2 dans une table qui n'a qu'un seul enregistrement. Je veux sélectionner les valeurs de cette table, puis les incrémenter en verrouillant la ligne en utilisant select pour la mise à jour.

merci.

Répondre

0

Vous devez vous assurer que autocommit est défini sur false sur votre connexion. C'est la clé. Ensuite, vous procédez comme suit:

  1. Faites votre sélection avec la clause mise à jour à la fin (sélectionnez colonne1, colonne2 de matable pour la mise à jour). Cela verrouillera la ligne.

  2. Effectuez votre requête de mise à jour.

  3. Emettez une validation explicite qui libérerait le verrou sur la ligne.

Bien sûr, rappelez-vous que le verrouillage de la ligne la verrouille de la modification. Une autre session pourrait encore interroger ces lignes. Par exemple, s'il s'agissait d'un ID et que le moyen de récupérer un nouvel ID était d'interroger la table en faisant select max(id) + 1 from table. Verrouiller la ligne n'empêcherait pas une autre session de sélectionner cette option.

Mieux encore serait d'ignorer la sélection et mettre à jour les enregistrements en place et utiliser la clause returning pour vous renvoyer les nouvelles valeurs mises à jour. Je ne l'ai jamais fait dans Ruby OCI8, donc je ne suis pas sûr si elle supporte cette fonctionnalité. Les documents pour cette clause dans une mise à jour sont ici:

http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10007.htm#i2126358

+0

Oui, je l'utilise comme une carte d'identité. Je veux sélectionner la valeur actuelle du compteur (pour l'utiliser comme identifiant) et incrémenter le compteur. Cela empêche-t-il une autre session de faire un 'select for update' au lieu de simplement 'select'. Avec 'select for update', deux sessions peuvent toujours obtenir le même identifiant. Je vais essayer la clause 'return'. Merci. – user290870

+0

@ ash34: Si une session a fait 'select for update' et qu'elle n'a pas encore été validée ou annulée, l'autre session effectuant un' select for update' bloquera l'attente pour pouvoir obtenir un verrou. Vous pouvez faire échouer rapidement l'autre session en utilisant 'select for update nowait'. Consultez une courte explication de nowait ici: http://docstore.mik.ua/orelly/oracle/prog2/ch06_11.htm –

+1

Si vous voulez un compteur fiable, vous devez utiliser une séquence. – Martlark

0
select_stmt = conn.prepare('select * from table_name for update') 
select_stmt.exec 
while row = select_stmt.fetch 
    conn.exec('update table_name set col = :1 where rowid = :2', 'val', select_stmt.rowid) 
end 
Questions connexes