执行值您需要重写或转换表达式

时间:2018-06-03 10:50:45

标签: python postgresql psycopg2

我正在尝试使用架构

执行批量插入
CREATE TABLE IF NOT EXISTS test (symbol VARCHAR(16), ts timestamp)

我有一个值数组要插入表单

[('AAPL',1528004700), ('AAPL', 1528005600)]

我的插入查询如下所示

insert into test VALUES %s

和我执行插入的python代码看起来像

psycopg2.extras.execute_values(cursor, insert_stmt, [('AAPL',1528004700), ('AAPL', 1528005600)])

我收到错误

ProgrammingError: column "ts" is of type timestamp without time zone but expression is of type integer
LINE 1: insert into test VALUES ('AAPL',1528004700),('AAPL',15280056...
                                        ^
HINT:  You will need to rewrite or cast the expression.

我理解to_timestamp可以在插入时修复此问题但是execute_values不允许我添加多个占位符,我需要每次都执行批量插入。时间戳应该没有时区。我该如何解决这个错误

谢谢!

更新1

execute_batch()工作正常,因为我能够在占位符部分添加to_timestamp

insert = "insert into test VALUES (%s, to_timestamp(%s))"

接着是

psycopg2.extras.execute_batch(cur, insert, [('AAPL',1528004700), ('AAPL', 1528005600)])

但是我想使用execute_values,因为它比execute_batch()

稍快

2 个答案:

答案 0 :(得分:1)

这应该有效:

from datetime import datetime
psycopg2.extras.execute_values(cursor, insert_stmt, [('AAPL',datetime.fromtimestamp(1528004700)), ('AAPL', datetime.fromtimestamp(1528005600))])

编辑: 一般来说,Postgres无法猜测您的1528004700是时间戳,您需要以某种方式明确说明它。你的解决方案带有to_timestamp位置"这是一个时间戳"在Postgres方面,上面的代码将它放在python端。从信息的角度来看,它们是等价的,我没有检查哪一个更有效。

答案 1 :(得分:0)

我不确定psycopg2.extras.execute_values,但通常的方法是使用executemany方法插入记录列表

每个列都使用%s编写insert语句。在这种特殊情况下,我们还需要将整数转换为时间戳。幸运的是,postgresql提供了一个to_timestamp函数来做到这一点。

values = [('AAPL',1528004700), ('AAPL', 1528005600)]
stmt = 'insert into test values (%s, to_timestamp(%s))'
cur.executemany(stmt, values)