2012-04-09 15 views
13

Estoy buscando un ejemplo completo del uso de seleccionar para actualizar en SQLAlchemy, pero no he encontrado uno en Google. Necesito bloquear una sola fila y actualizar una columna, el código siguiente no funciona (bloques para siempre):SQLAlchemy - seleccionar para el ejemplo de actualización

s = table.select(table.c.user=="test",for_update=True) 
# Do update or not depending on the row 
u = table.update().where(table.c.user=="test")   
u.execute(email="foo") 

¿Necesito una confirmación? ¿Cómo puedo hacer eso? Por lo que yo sé lo que necesita: begin transaction seleccione ... para la actualización actualización cometer

+1

queremos dejar de señalar el objeto de consulta tiene un nuevo método para esto: http://docs.sqlalchemy.org/en/rel_0_9 /orm/query.html#sqlalchemy.orm.query.Query.with_for_update –

Respuesta

2

Sí, sí es necesario comprometerse, que se puede ejecutar en el Engine o crear una Transaction explícitamente. También los modificadores se especifican en el método values(...), y no execute:

>>> conn.execute(users.update(). 
...    where(table.c.user=="test"). 
...    values(email="foo") 
...    ) 
>>> my_engine.commit() 
+2

Esta respuesta omite el punto principal de la pregunta dada, que es el ejemplo de uso 'SELECT ... FOR UPDATE'. El código de este se puede reducir a la forma propuesta, pero ya no usa la construcción solicitada. Por supuesto, si @Mark no planea agregar ninguna lógica adicional entre obtener el bloqueo y actualizar los registros, dicha reducción está perfectamente bien. – RobertT

6

respuesta tardía, pero tal vez alguien lo encontrarán útil.

En primer lugar, no es necesario confirmar (al menos, no entre las consultas, que estoy suponiendo que está preguntando). Su segunda consulta se cuelga indefinidamente, porque está creando efectivamente dos conexiones concurrentes a la base de datos. El primero es obtener el bloqueo en los registros seleccionados, luego el segundo intenta modificar los registros bloqueados. Entonces no puede funcionar correctamente. (Por cierto en el ejemplo dado, no estás llamando a la primera consulta, así que supongo que en tus pruebas reales hiciste algo como s.execute() en algún lugar). Así que para la implementación de punto de trabajo debe verse más como:

s = conn.execute(table.select(table.c.user=="test", for_update=True)) 
u = conn.execute(table.update().where(table.c.user=="test), {"email": "foo"}) 
conn.commit() 

Por supuesto, en tal caso simple que no hay razón para hacer cualquier bloqueo, pero supongo que es ejemplo y se planea añadir algo de lógica adicional entre los dos llamadas.

7

Si está utilizando el ORM, pruebe la función with_for_update:

 
foo = session.query(Foo).filter(Foo.id==1234).with_for_update().one() 
# this row is now locked 

foo.name = 'bar' 
session.add(foo) 

session.commit() 
# this row is now unlocked 
+0

Debería haber Foo.id == 1234. Referencia: http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.filter – Kapucko

+0

@Kapucko Gracias; editado –

+0

@MatthewMoisen ¿podría decirme por qué usar 'add'? si no lo uso, ¿estará bien? –

Cuestiones relacionadas