Tôi có mô hình/bảng Test
và mô hình TestAuditLog
/bảng, sử dụng SQLAlchemy và SQL Server 2008. Mối quan hệ giữa hai là Test.id == TestAuditLog.entityId
, với một thử nghiệm có nhiều kiểm tra nhật ký. TestAuditLog
nhằm giữ lịch sử thay đổi đối với các hàng trong bảng Test
. Tôi cũng muốn theo dõi thời điểm Test
cũng bị xóa nhưng tôi đang gặp sự cố với điều này. Trong SQL Server Management Studio, tôi đặt thuộc tính "Enforce Foreign Key Constraint" của mối quan hệ là "" thành "Không", cho phép hàng TestAuditLog
tồn tại với entityId
không còn kết nối với bất kỳ Test.id
nào vì Test
đã bị xóa. Tuy nhiên, khi tôi cố gắng để tạo ra một TestAuditLog
với SQLAlchemy và sau đó xóa các Test
, tôi nhận được một lỗi:SQLAlchemy - không thực thi ràng buộc khóa ngoài đối với mối quan hệ
(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)
Tôi nghĩ rằng vì mối quan hệ ngoại-key giữa Test
và TestAuditLog
, sau khi tôi xóa hàng Test
, SQLAlchemy đang cố gắng cập nhật tất cả nhật ký kiểm tra của thử nghiệm để có một NULL
entityId
. Tôi không muốn nó làm điều này; Tôi muốn SQLAlchemy để lại các bản ghi kiểm toán một mình. Làm cách nào tôi có thể yêu cầu SQLAlchemy cho phép nhật ký kiểm tra tồn tại có entityId
không kết nối với bất kỳ Test.id
nào?
tôi đã cố gắng chỉ loại bỏ các ForeignKey
từ các bảng của tôi, nhưng tôi muốn vẫn có thể nói myTest.audits
và nhận được tất cả các bản ghi kiểm toán của kiểm tra, và SQLAlchemy phàn nàn về việc không biết làm thế nào để tham gia Test
và TestAuditLog
. Khi tôi sau đó chỉ định một primaryjoin
trên relationship
, nó càu nhàu về việc không có ForeignKey
hoặc ForeignKeyConstraint
với các cột.
Dưới đây là mô hình của tôi:
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")
...
Và dưới đây là cách tôi đang cố gắng để xóa một bài kiểm tra trong khi vẫn giữ các bản ghi kiểm toán, họ entityId
nguyên vẹn:
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
'passive_deletes = 'all'' trên' relationship' đã làm điều đó!Bằng cách đó tôi đã có thể giữ các mối quan hệ và SQLAlchemy đã không quay trở lại và cố gắng xóa sạch 'entityId' trên' Test'. Cảm ơn! –
Chỉ cần tham khảo - nó sẽ được yêu cầu cũng đặt 'lazy =" dynamic "' ở phía cha mẹ của mối quan hệ vì vậy sqlalchemy sẽ không lấy tất cả các con khi bạn không cần nó (tức là khi chỉ cập nhật một trường không liên quan trong bảng cha). – Greg0ry
@ Greg0ry: Không, bạn không cần. Như được ghi chép trong [Sử dụng các chiến lược bộ nạp: Tải xuống tải xuống, tải công việc tải xuống] (http://docs.sqlalchemy.org/en/rel_1_0/orm/loading_relationships.html#using-loader-strategies-lazy-loading-eager-loading): * Theo mặc định, tất cả các mối quan hệ giữa các đối tượng đều tải xuống ... *. Vì vậy, trừ khi bạn làm khác, cha mẹ không nên tải trẻ em trừ khi bạn truy cập chúng. – van