python - query - sqlalchemy tutorial
SQLAlchemy: realizar una inserciĆ³n masiva(si existe, actualizar, sino insertar) en postgresql (1)
Esta pregunta ya tiene una respuesta aquí:
Estoy intentando escribir un aumento de volumen en python utilizando el módulo SQLAlchemy (¡no en SQL!).
Estoy recibiendo el siguiente error en un SQLAlchemy add:
sqlalchemy.exc.IntegrityError: (IntegrityError) duplicate key value violates unique constraint "posts_pkey"
DETAIL: Key (id)=(TEST1234) already exists.
Tengo una tabla llamada posts
con una clave principal en la columna de id
.
En este ejemplo, ya tengo una fila en la base de datos con id=TEST1234
. Cuando intento db.session.add()
un nuevo objeto de publicaciones con el id
establecido en TEST1234
, TEST1234
el error anterior. Tenía la impresión de que si la clave principal ya existe, el registro se actualizaría.
¿Cómo puedo realizar una inserción con Flask-SQLAlchemy solo en base a la clave principal? ¿Hay una solución simple?
Si no lo hay, siempre puedo buscar y eliminar cualquier registro con un ID coincidente, y luego insertar el nuevo registro, pero eso parece costoso para mi situación, donde no espero muchas actualizaciones.
Hay una operación de upsert-esque en SQLAlchemy:
db.session.merge()
Después de que encontré este comando, pude realizar actualizaciones, pero vale la pena mencionar que esta operación es lenta para una "elevación superior".
La alternativa es obtener una lista de las claves primarias que le gustaría modificar, y consultar la base de datos para cualquier identificación que coincida:
# Imagine that post1, post5, and post1000 are posts objects with ids 1, 5 and 1000 respectively
# The goal is to "upsert" these posts.
# we initialize a dict which maps id to the post object
my_new_posts = {1: post1, 5: post5, 1000: post1000}
for each in posts.query.filter(posts.id.in_(my_new_posts.keys())).all():
# Only merge those posts which already exist in the database
db.session.merge(my_new_posts.pop(each.id))
# Only add those posts which did not exist in the database
db.session.add_all(my_new_posts.values())
# Now we commit our modifications (merges) and inserts (adds) to the database!
db.session.commit()