【问题标题】:python : sqlalchemy batch insert with on_conflict_updatepython:使用 on_conflict_update 的 sqlalchemy 批量插入
【发布时间】:2018-09-18 12:23:23
【问题描述】:

我必须插入大约。我的 postgres 数据库中每天有 30000 行, 我的数据库中有 4 列,即: id(pkey)、类别、创建日期、更新日期。 我的要求是使用今天的日期和新类别更新更新和类别列(如果 id 存在),否则插入一个新行,其中 createddate 和 updateon 相同

我找到了 Ilja Everilä 的 [answer]:https://stackoverflow.com/a/44865375/5665430 进行批量更新

insert_statement = sqlalchemy.dialects.postgresql.insert(id_tag)
upsert_statement = insert_statement.on_conflict_do_update(
        constraint='id',
    set_={ "createddate": insert_statement.excluded.createddate }
)
insert_values = df.to_dict(orient='records')
conn.execute(upsert_statement, insert_values)

它抛出 AttributeError,

Traceback (most recent call last):

File "<ipython-input-60-4c5e5e0daf14>", line 5, in <module>
    set_= dict(createddate = insert_statement.excluded.createddate)

File "/home/bluepi/anaconda2/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 764, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)

  File "/home/bluepi/anaconda2/lib/python2.7/site-packages/sqlalchemy/dialects/postgresql/dml.py", line 43, in excluded
    return alias(self.table, name='excluded').columns

  File "/home/bluepi/anaconda2/lib/python2.7/site-packages/sqlalchemy/sql/selectable.py", line 161, in alias
    return _interpret_as_from(selectable).alias(name=name, flat=flat)

AttributeError: 'TextClause' object has no attribute 'alias'

我已经尝试过一一更新,如此处所示 http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#postgresql-insert-on-conflict ,但我得到了同样的错误。

请帮助我了解我哪里出错了,在此先感谢。

【问题讨论】:

  • @IljaEverilä 我什么都没做,只是根据我的要求更改了字段,仅此而已。我认为问题出在这行代码 insert_statement.excluded.createddate
  • @IljaEverilä 添加了追溯
  • @IljaEverilä 这是我的表名
  • @IljaEverilä 没听懂
  • @IljaEverilä id_tag 只是我在 postgres 中桌子的鬃毛

标签: python sqlalchemy psql


【解决方案1】:

来自您的评论

id_tag 只是我在 postgres 中的表的鬃毛

可以推断id_tag 绑定到一个字符串。如果您提供了Minimal, Complete, and Verifiable example,那么猜测就会少很多。事实证明,postgresql.dml.insert() 自动将传递的字符串包装在 text() 构造中,尝试使用 Insert.excluded 时的结果是:

In [2]: postgresql.insert('fail').excluded
~/sqlalchemy/lib/sqlalchemy/sql/selectable.py:43: SAWarning: Textual SQL FROM expression 'fail' should be explicitly declared as text('fail'), or use table('fail') for more specificity (this warning may be suppressed after 10 occurrences)
  {"expr": util.ellipses_string(element)})
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-2-f176aac8b913> in <module>()
----> 1 postgresql.insert('fail').excluded

~/sqlalchemy/lib/sqlalchemy/util/langhelpers.py in __get__(self, obj, cls)
    765         if obj is None:
    766             return self
--> 767         obj.__dict__[self.__name__] = result = self.fget(obj)
    768         return result
    769 

~/sqlalchemy/lib/sqlalchemy/dialects/postgresql/dml.py in excluded(self)
     41 
     42         """
---> 43         return alias(self.table, name='excluded').columns
     44 
     45     @_generative

~/sqlalchemy/lib/sqlalchemy/sql/selectable.py in alias(selectable, name, flat)
    159 
    160     """
--> 161     return _interpret_as_from(selectable).alias(name=name, flat=flat)
    162 
    163 

AttributeError: 'TextClause' object has no attribute 'alias'

因此,与其将包含表名称的字符串传递给 postgresql.dml.insert(),不如将​​其传递给实际的 Table 对象,或已填充有 column() 对象的轻量级 table() 构造。

【讨论】:

  • 我做了你在答案中提到的更改,现在我收到一个新错误,sqlalchemy on_conflict_do_update 文档不清楚。我尝试调试错误。
猜你喜欢
  • 2011-04-09
  • 2017-01-01
  • 1970-01-01
  • 2017-01-20
  • 2015-11-06
  • 2016-11-29
  • 2019-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多