[英]Trouble with Flask / Jinja2 conditional statement - displaying sqlalchemy class
[英]conditional add statement in SQLAlchemy
假設我想將幾個SQL記錄上載到可能尚未填充的表中。 如果在表或要提交到表的記錄中已經存在具有主鍵(“ ID”)的記錄,我想用新記錄替換現有記錄。 我正在使用mssql,SQL Server 2008。
我的第一個猜測是
try:
session.add(record)
session.commit
except:
session.query().\
filter(Class.ID == record.ID).\
update(some expression)
session.commit()
表達式應該是什么? 有沒有更清潔(更安全!)的方法呢?
通常,除非使用保證原子性的語句,否則您將始終必須考慮可能由於多個參與者嘗試插入或更新(不要忘記刪除)而引起的競爭條件。 即使使用MERGE語句 (即使是單個語句),如果使用不正確也可能具有競爭條件 。
傳統上,這種“更新”是使用存儲過程或其他SQL或特定於實現的特定功能(例如MERGE語句)執行的。
如果出現完整性錯誤,SQLAlchemy解決方案必須嘗試插入並執行更新,如果不影響任何行,則執行udpate並嘗試插入。 如果兩個操作都失敗(在該行之間可能會刪除或插入一行),則應准備重試:
from sqlalchemy.exc import IntegrityError
while True: # Infinite loop, use a retry counter if necessary
try:
# begin a save point, prevents the whole transaction failing
# in case of an integrity error
with session.begin_nested():
session.add(record)
# Flush instead of commit, we need the transaction intact
session.flush()
# If the flush is successful, break out of the loop as the insert
# was performed
break
except IntegrityError:
# Attempt the update. If the session has to reflect the changes
# performed by the update, change the `synchronize_session` argument.
if session.query(Class).\
filter_by(ID=record.ID).\
update({...},
syncronize_session=False):
# 1 or more rows were affected (hopefully 1)
break
# Nothing was updated, perhaps a DELETE in between
# Both operations have failed, retry
session.commit()
關於
如果在表或要提交到表的記錄中已經存在具有主鍵(“ ID”)的記錄,我想用新記錄替換現有記錄。
如果您可以確定不會對該表進行任何並發更新,則可以將Session.merge
用於此類任務:
# Records have primary key set, on which merge can either load existing
# state and merge, or create a new record in session if none was found.
for record in records:
merged_record = session.merge(record)
# Note that merged_record is not record
session.commit()
SQLAlchemy合並將首先檢查身份映射中是否存在具有給定主鍵的實例。 如果沒有,並且load
作為True
傳遞,它將檢查數據庫中的主鍵。 如果給定實例沒有主鍵或找不到實例,則將創建一個新實例。
然后,合並會將給定實例的狀態復制到已定位/創建的實例上。 返回新實例。
否。這樣做有更好的模式。 首先執行查詢以查看記錄是否已經存在,然后進行相應的處理。
使用您的語法,將類似於以下內容:
result = session.query().filter(Class.ID == record.ID).first()
# If record does not exist in Db, then add record
if result is None:
try:
session.add(record)
session.commit()
except:
db.rollback()
log.error('Rolling back transaction in query-none block')
# If record does exist, then update value of record in Db
else:
try:
session.query().\
filter(Class.ID == record.ID).\
update(some expression)
session.commit()
except:
db.rollback()
log.error('Rolling back transaction')
將數據庫操作包裝在try / except塊中通常是一個好主意,因此您可以對嘗試的部分進行正確的編寫。 根據您的操作,except塊通常應顯示一條錯誤消息或執行數據庫回滾。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.