Tengo un modelo/tabla Test
y un modelo/tabla TestAuditLog
, usando SQLAlchemy y SQL Server 2008. La relación entre los dos es Test.id == TestAuditLog.entityId
, con una prueba que tiene muchas auditorías registros TestAuditLog
está destinado a mantener un historial de cambios en las filas en la tabla Test
. Quiero rastrear cuando se borra un Test
, también, pero estoy teniendo problemas con esto. En SQL Server Management Studio, establecí la propiedad FK_TEST_AUDIT_LOG_TEST
de la relación "Enforce Foreign Key Constraint" en "No", pensando que permitiría una fila TestAuditLog
existir con un entityId
que ya no se conecta con ningún Test.id
porque se ha eliminado el Test
. Sin embargo, cuando intento crear un TestAuditLog
con SQLAlchemy y elimine la Test
, me sale un error:SQLAlchemy: no aplicar la restricción de clave externa en una relación
(IntegrityError) ('23000', "[23000] [Microsoft][ODBC SQL Server Driver][SQL Server]Cannot insert the value NULL into column 'AL_TEST_ID', table 'TEST_AUDIT_LOG'; column does not allow nulls. UPDATE fails. (515) (SQLExecDirectW); [01000] [Microsoft][ODBC SQL Server Driver][SQL Server]The statement has been terminated. (3621)") u'UPDATE [TEST_AUDIT_LOG] SET [AL_TEST_ID]=? WHERE [TEST_AUDIT_LOG].[AL_ID] = ?' (None, 8)
Creo que debido a la relación de clave externa entre Test
y TestAuditLog
, después de eliminar la fila Test
, SQLAlchemy intenta actualizar todos los registros de auditoría de la prueba para tener un NULL
entityId
. No quiero que haga esto; Quiero que SQLAlchemy deje los registros de auditoría solo. ¿Cómo puedo decirle a SQLAlchemy que permita que existan registros de auditoría cuyo entityId
no se conecte con ningún Test.id
?
me trataron sólo la eliminación de la ForeignKey
de mis cuadros, pero me gustaría seguir siendo capaz de decir myTest.audits
y obtener todos los registros de auditoría de una prueba, y SQLAlchemy se quejaron de no saber cómo unirse Test
y TestAuditLog
. Cuando especifiqué un primaryjoin
en el relationship
, se quejaba de no tener un ForeignKey
o ForeignKeyConstraint
con las columnas.
Éstos son mis modelos:
class TestAuditLog(Base, Common):
__tablename__ = u'TEST_AUDIT_LOG'
entityId = Column(u'AL_TEST_ID', INTEGER(), ForeignKey(u'TEST.TS_TEST_ID'),
nullable=False)
...
class Test(Base, Common):
__tablename__ = u'TEST'
id = Column(u'TS_TEST_ID', INTEGER(), primary_key=True, nullable=False)
audits = relationship(TestAuditLog, backref="test")
...
Y es como yo estoy tratando de eliminar una prueba, manteniendo sus registros de auditoría aquí, su entityId
intactos:
test = Session.query(Test).first()
Session.begin()
try:
Session.add(TestAuditLog(entityId=test.id))
Session.flush()
Session.delete(test)
Session.commit()
except:
Session.rollback()
raise
¡El 'pasivo_delete = 'all'' en la' relación' lo hizo!De esa forma pude mantener las relaciones y SQLAlchemy no retrocedió e intentó eliminar el 'entityId' en la eliminación de' Test'. ¡Gracias! –
Solo como referencia: también se requiere establecer 'lazy =" dynamic "' en el lado padre de la relación para que sqlalchemy no busque todos los elementos secundarios cuando no lo necesite (es decir, al actualizar un campo irrelevante en la tabla padre)) – Greg0ry
@ Greg0ry: No, no es necesario. Como se documenta en [Uso de estrategias de cargador: carga lenta, carga lenta] (http://docs.sqlalchemy.org/en/rel_1_0/orm/loading_relationships.html#using-loader-strategies-lazy-loading-eager-loading): * Por defecto, todas las relaciones entre objetos son carga lenta ... *. A menos que lo haga de otra manera, el padre no debe cargar hijos a menos que usted tenga acceso a ellos. – van