问题 在sqlalchemy中的Postgresql ON CONFLICT


我读了很多资源(ao。 12)但是我无法在sqlalchemy中使用Postgresql的ON CONFLICT IGNORE行为。

我用过 这个接受的答案 作为基础,但它给出了

SAWarning: Can't validate argument 'append_string'; can't locate any SQLAlchemy dialect named 'append'

我已经尝试将postgresql方言添加到@compile子句,重命名我的对象,但它不起作用。 我也试过用 str(insert())+ " ON CONFILCT IGNORE" 没有结果。 (顺便说一句,这并不奇怪)

我怎么能得到 On CONFLICT IGNORE 要添加到我的插入?我喜欢提出的解决方案,因为我可以看到自己不想要的 IGNORE 每个人的行为 INSERT

PS。使用python 2.7(不介意升级到3.4 / 3.5),最新的sqlalchemy(1.x)


7709
2017-10-23 16:28


起源

你应该提供示例代码,因为如果这个接受的答案你提到你的工作(你测试过吗?测试它!)更改UPNATE到IGNORE也应该工作或你有一个错字。但是,如果您提到的代码也不起作用,您可能还有其他问题。 - omikron


答案:


你不需要这个,使用存在条件来防止插入重复。

例如:

INSERT INTO table (unique_name) 
SELSCT 'some_string'
WHERE NOT EXISTS(SELECT 1 FROM table WHERE unique_name = 'some_string')

你也可以

INSERT INTO table (unique_name)
VALUES('some_string')
ON CONFLICT (unique_name) DO NOTHING

但如果你需要  或者在单个查询中更新,那么这是您的示例:

INSERT INTO distributors (did, dname)
VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;

这是PostgreSQL文档中的示例。


3
2018-04-02 19:01



请问示例代码?如何使用exists条件在单个语句中插入或更新? - Kiran Jonnalagadda
谢谢!这有帮助。 - Kiran Jonnalagadda
错过了投票。固定。虽然我没有提出这个问题,但不能将其标记为正确的答案。 - Kiran Jonnalagadda
我问了这个问题,但我仍然不理解它是如何工作的 sqlalchemy - puredevotion
你问:如何在sqlalchemy中使用SQL?如果是,请阅读 这个。如果没有发布您的代码,因为我不知道您的代码是如何工作的。 - Adam Silenko


使用Postgres 9.6.1,sqlachemy 1.1.4和psycopg2 2.6.2:

  1. 将数据结构转换为字典。从熊猫那里来的

    import pandas
    from sqlalchemy import MetaData
    from sqlalchemy.dialects.postgresql import insert
    import psycopg2
    
    # The dictionary should include all the values including index values
    insrt_vals = df.to_dict(orient='records')
    
  2. 通过sqlalchemy连接到数据库

    engine = sqlalchemy.create_engine("postgresql://user:password@localhost/postgres")
    connect = engine.connect()
    meta = MetaData(bind=engine)
    meta.reflect(bind=engine)
    
  3. 构造一个插入语句 db table 叫 tstbl

    table = meta.tables['tstbl']
    insrt_stmnt = insert(table).values(insrt_vals)
    
    # Where colA and colB are the columns to check for the conflict
    do_nothing_stmt  = insrt_stmnt.on_conflict_do_nothing(index_elements=['colA','colB'])
    
  4. 执行

    results = engine.execute(do_nothing_stmt)
    # Get number of rows inserted
    rowcount = results.rowcount
    

警告:

此方法不起作用 NaT开箱即用。

一切都在一起

tst_df = pd.DataFrame({'colA':['a','b','c','a','z', 'q'],
              'colB': pd.date_range(end=datetime.datetime.now() , periods=6),
              'colC' : ['a1','b2','c3','a4','z5', 'q6']})


insrt_vals = tst_df.to_dict(orient='records')
engine =      sqlalchemy.create_engine("postgresql://user:password@localhost/postgres")
connect = engine.connect()
meta = MetaData(bind=engine)
meta.reflect(bind=engine)
table = meta.tables['tstbl']
insrt_stmnt = insert(table).values(insrt_vals)

do_nothing_stmt  = insrt_stmnt.on_conflict_do_nothing(index_elements=['colA','colB'])
results = engine.execute(do_nothing_stmt)

10
2017-12-20 08:53





这适用于Postgresql 9.5:

from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import Insert

@compiles(Insert)
def prefix_inserts(insert, compiler, **kw):
    return compiler.visit_insert(insert, **kw) + " ON CONFLICT DO NOTHING"

我用它 bulk_insert_mappings。然而它确实没有 ON CONFLICT DO NOTHING 可选的


3
2018-04-29 09:59