SQLAlchemy – seleccionar para el ejemplo de actualización

Estoy buscando un ejemplo completo de uso de select for update en SQLAlchemy, pero no he encontrado un solo googlear. Necesito bloquear una sola fila y actualizar una columna, el siguiente código no funciona (se bloquea para siempre):

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 un commit? ¿Cómo puedo hacer eso? Por lo que sé, debe: comenzar la selección de transacciones … para confirmar la actualización de actualización

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

 foo = session.query (Foo) .filter (Foo.id == 1234) .with_for_update (). one ()
 # esta fila ahora está bloqueada

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

 session.commit ()
 # esta fila ahora está desbloqueada

Respuesta tardía, pero tal vez alguien lo encuentre útil.

Primero, no necesita comprometerse (al menos no entre las consultas, que supongo que usted pregunta). Su segunda consulta se cuelga indefinidamente, porque está creando efectivamente dos conexiones simultáneas a la base de datos. El primero es obtener el locking en los registros seleccionados, luego el segundo intenta modificar los registros bloqueados. Así que no puede funcionar correctamente. (Por cierto, en el ejemplo dado, no está llamando a la primera consulta, así que supongo que en sus pruebas reales hizo algo como s.execute() algún lugar). Entonces, al punto, la implementación de trabajo debería parecerse más a:

 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 un caso tan simple no hay ninguna razón para hacer ningún locking, pero supongo que es solo un ejemplo y usted planeaba agregar alguna lógica adicional entre esas dos llamadas.

Sí, debe comprometerse, lo que puede ejecutar en el Engine o crear una Transaction explícitamente. Además, los modificadores se especifican en el método de values(...) y no se execute :

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