[英]How to create an identity column not being a primary key with SQLAlchemy?
[英]How can I create a sqlalchemy column whose default is to be equal to the primary key?
我有一堂課,看起來像這樣:
class Foo(Base):
pk = Column(Integer, Sequence('foo'), primary_key=True)
我想創建另一個字段ref
,它默認等於新創建對象的pk
。 不幸的是,我使用的是Postgres,它具有一個非標准的nextval()
函數 ,因此我不能簡單地將這兩列都默認設置為Sequence對象。
這是我當前的解決方案:
class Foo(Base):
pk = Column(Integer, Sequence('foo'), primary_key=True)
ref = Column(Integer, index=True, nullable=False, default=func.currval('foo'))
但是,這取決於兩件事:SQLAlchemy生成一個在ref
之前帶有pk
的INSERT語句, 以及 Postgres從左到右評估表達式(因此pk
生成的nextval()
調用始終發生在ref
生成的currval
調用之前)。
對於如何更好地做到這一點,我將不勝感激!
編輯:還有更多的解決方案,設置default=-1
或類似的東西,並強制調用方更新ref
字段。 對於SQLA / Postgres語義的更改而言,這更安全,更可靠,但對於類的客戶而言卻非常不便。
可以利用SQLAlchemy的ORM after_insert
映射器事件:
from sqlalchemy import event
# Model from OP
class Foo(Base):
pk = Column(Integer, Sequence('foo'), primary_key=True)
ref = Column(Integer, index=True, nullable=False, default=-1)
@staticmethod
def fill_ref(mapper, connection, target):
# Note: You cannot use ORM in the event callbacks
connection.execute(mapper.mapped_table.update()
.values(ref=target.pk))
.where(table.c.pk==target.pk))
event.listen(Foo, 'after_insert', Foo.fill_ref)
我建議使用觸發器來設置該值。 盡管我自己尚未對此進行測試,但是您可以使觸發器激活AFTER INSERT,該觸發器讀取新行的PK值並使用該值更新ref列。 似乎有點類似於Postgresql插入觸發器來設置值,不同的是您希望觸發器在插入之后而不是之前。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.