【问题标题】:psycopg2.errors.UniqueViolation on Sqlalchemy's merge()psycopg2.errors.UniqueViolation 上 Sqlalchemy 的 merge()
【发布时间】:2021-01-15 04:02:29
【问题描述】:

我有一个带有复合主键的模型 我正在尝试使用 sqlalchemy 的 merge() 方法执行 upsert。 出于某种原因,它在我的其他测试模型上运行良好(复合键总共由 7 个列组成),但在这个模型上却很难通过

class Offsets(db.Model, CommonMethods):
    symbol_id = db.Column(db.String(120), primary_key=True)
    account_id = db.Column(db.String(120), primary_key=True)
    settlement_counterparty = db.Column(db.String(120), primary_key=True)
    execution_counterparty = db.Column(db.String(120), primary_key=True)
    counterparty_account_id = db.Column(db.String(120))
    trade_date = db.Column(db.String(10), primary_key=True)

    daily_diff = db.Column(db.String(120))
    buy_qty = db.Column(db.String(120))
    sell_qty = db.Column(db.String(120))
    pos_before_trade = db.Column(db.String(120))
    pos_after_trade = db.Column(db.String(120))
    
    
    offset =  db.Column(db.String(120))#resulting offset

    related_orders = db.Column(db.ARRAY(db.String(360)))

    comment = db.Column(db.String(360))

    manual = db.Column(db.Boolean, default=False, primary_key=True)
    settlement = db.Column(db.Boolean, default=False, primary_key=True) #for some reason if i remove this from model, merging goes fine

下面我正在尝试执行 upsert

app=create_app()
app.app_context().push()

entry=Offsets(
        trade_date='2020-09-29',
        symbol_id='AAPL',
        account_id='FOO',
        buy_qty='0',
        settlement_counterparty='BAR',
        execution_counterparty='BAZ',
        counterparty_account_id='FOOBARBAZ',
        sell_qty='1',
        daily_diff='1',
        related_orders=['some_uuids_here'],
        manual=False
    )

db.session.merge(entry)
<Offsets (transient 140184049284712)>
db.session.commit()#first went fine as it wasnt in db
None
db.session.merge(entry)
<Offsets (transient 140184049535072)>
db.session.commit()#second time it returns an error though
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.6/dist-packages/sqlalchemy/orm/scoping.py", line 162, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/sqlalchemy/orm/session.py", line 1027, in commit
    self.transaction.commit()
  File "/usr/local/lib/python3.6/dist-packages/sqlalchemy/orm/session.py", line 492, in commit
    self._assert_active(prepared_ok=True)
  File "/usr/local/lib/python3.6/dist-packages/sqlalchemy/orm/session.py", line 295, in _assert_active
    code="7s2a",
sqlalchemy.exc.InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback(). Original exception was: (psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint "offsets_pkey"
DETAIL:  Key (symbol_id, account_id, settlement_counterparty, execution_counterparty, trade_date, manual, settlement)=(AAPL, FOO, BAR, BAZ, 2020-09-29, f, f) already exists.

上面的代码不应该在没有错误的情况下执行 upsert(在冲突时更新非主键 cols)吗?

【问题讨论】:

    标签: python merge sqlalchemy upsert


    【解决方案1】:

    在创建entry 时,我必须明确定义settlement = False,由于某种原因,模型中的default=False 还不够

    【讨论】:

      猜你喜欢
      • 2022-11-10
      • 2012-01-25
      • 1970-01-01
      • 2011-11-06
      • 2012-10-18
      • 2016-08-26
      • 2013-11-16
      • 2020-12-07
      • 2020-07-16
      相关资源
      最近更新 更多