2017-04-11 62 views
1

尝试对PostgreSQL> 9.5的值数组执行UPSERT。SQLAlchemy PostgreSQL UPSERT数组值

试图构建SQLALchemy文档中的语句,但没有解释如何为数组而不是单行执行此操作。 insert语句的构建正确,所以我想可以使用on_conflict_do_update函数来完成。

有了这个代码:

stock_table = Table("stock_history", metadata, 
      Column('date', sqlalchemy.types.NVARCHAR(length=255), primary_key=True), 
      Column('product_id', sqlalchemy.types.INTEGER(), primary_key=True), 
      Column('product_sku', sqlalchemy.types.NVARCHAR(length=255)), 
      Column('on_hand_qty', sqlalchemy.dialects.postgresql.DOUBLE_PRECISION()), 
      Column('available_qty', sqlalchemy.dialects.postgresql.DOUBLE_PRECISION()), 
      Column('output_qty', sqlalchemy.dialects.postgresql.DOUBLE_PRECISION()) 
     ) 
stock_today = pandas.read_sql_query(queryStock, odoo_engine) 
insert_stmt = sqlalchemy.dialects.postgresql.insert(stock_table).values(stock_today) 
upser_stmt = insert_stmt.on_conflict_do_update(
      index_elements=['date', 'product_id'], 
      set_=stock_today.to_dict(orient='dict') 
     ) 

,我发现了以下错误:

AttributeError的: 'StrSQLCompiler' 对象有没有属性 'visit_on_conflict_do_update'

During handling of the above exception, another exception occurred: 

    Traceback (most recent call last): 
     File "pompeiiETL.py", line 15, in <module> 
     pompeiiJobs.runStockJob(dwh_engine, odoo_prod_engine) 
     File "/Users/alex/Development/DataLab/pompeii-datalab/pompeiiETL/jobs.py", line 54, in runStockJob 
     print(upser_stmt) 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 446, in __str__ 
     return str(self.compile()) 
     File "<string>", line 1, in <lambda> 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 436, in compile 
     return self._compiler(dialect, bind=bind, **kw) 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 442, in _compiler 
     return dialect.statement_compiler(dialect, self, **kw) 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/compiler.py", line 435, in __init__ 
     Compiled.__init__(self, dialect, statement, **kwargs) 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/compiler.py", line 216, in __init__ 
     self.string = self.process(self.statement, **compile_kwargs) 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/compiler.py", line 242, in process 
     return obj._compiler_dispatch(self, **kwargs) 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch 
     return meth(self, **kw) 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/compiler.py", line 2041, in visit_insert 
     insert_stmt._post_values_clause, **kw) 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/compiler.py", line 242, in process 
     return obj._compiler_dispatch(self, **kwargs) 
     File "/Users/alex/Development/DataLab/ETLenv/lib/python3.6/site-packages/sqlalchemy/sql/visitors.py", line 79, in _compiler_dispatch 
     raise exc.UnsupportedCompilationError(visitor, cls) 
    sqlalchemy.exc.UnsupportedCompilationError: Compiler <sqlalchemy.sql.compiler.StrSQLCompiler object at 0x105b55be0> can't render element of type <class 'sqlalchemy.dialects.postgresql.dml.OnConflictDoUpdate'> 

我是什么丁错了?有没有更好的方法来做一个upsert?

谢谢!

回答

2

您正试图获得Insert -object有没有适当的绑定,如果我们写

db_uri = make_url('your-postgres-db-uri-here') 
engine = create_engine(db_uri) 
upser_stmt.bind = engine 
print(upser_stmt) 

它的工作原理

我们还可以用绑定指定

insert_stmt = sqlalchemy.dialects.postgresql.insert(stock_table, 
                bind=engine).values(stock_today) 
upser_stmt = insert_stmt.on_conflict_do_update(
    index_elements=['date', 'product_id'], 
    set_=stock_today.to_dict(orient='dict') 
) 
创建插入语句的字符串表示
+0

嘿!谢谢!在你的帮助下,我设法按如下方式执行Insert插入: 'insert_stmt = sqlalchemy.dialects.postgresql.insert(stock_table,bind = dwh_engine).values(stock_today.to_dict(orient ='records'))' 但是如果我尝试添加on_conflict_do_update,添加相同的数据,我得到一个错误: 'raise ValueError(“设置参数必须是非空字典”) ValueError:设置参数必须是非空字典' 它是如何为插件工作,并说它是upsert空的? :S –

+0

随意问另一个问题,但不是在评论:更多的用户可以帮助你 –

+0

对我来说错误信息是明确的:你需要检查你的'set_'参数是否是一个非空字典 –