Psycopg2 execute_values 将所有值作为文本发送
Psycopg2 execute_values sending all values as text
我在 postgres
中有这个 table
CREATE TABLE target (
a json
b integer
c text []
id integer
CONSTRAINT id_fkey FOREIGN KEY (id)
REFERENCES public.other_table(id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
)
我想使用
从 psycopg2 插入数据
import psycopg2
import psycopg2.extras as extras
# data is of the form dict, integer, list(string), string <- used to get fkey id
data = [[extras.Json([{'a':1,'b':2}, {'d':3,'e':2}]), 1, ['hello', 'world'], 'ident1'],
[extras.Json([{'a':4,'b':3}, {'d':1,'e':9}]), 5, ['hello2', 'world2'], 'ident2']]
# convert data to list of tuples containing objects
x = [tuple(u) for u in data]
# insert data to the database
query = ('WITH ins (a, b, c, ident) AS '
'(VALUES %s) '
'INSERT INTO target (a, b, c, id) '
'SELECT '
'ins.a '
'ins.b '
'ins.c '
'other_table.id'
'FROM '
'ins '
'LEFT JOIN other_table ON ins.ident = other_table.ident;')
cursor = conn.cursor()
extras.execute_values(cursor, query, x)
当我 运行 这个时,我得到了 error: column "a" is of type json but expression is of type text
。我试图通过在 SELECT 语句中添加类型转换来解决这个问题,但后来我对 c 和 b.
都遇到了同样的错误
最初我认为问题在于 WITH 语句,但根据我之前问题的答案,情况似乎并非如此
似乎 execute_values
将所有值作为带有 ' '
的文本发送。
主要问题: 我怎样才能让 execute_values
发送基于 python 数据类型的值,而不是仅仅文字?
子问题:
我如何确认 execute_values
实际上是以带引号的文本形式发送值?
execute_values
https://www.psycopg.org/docs/extras.html 的模板参数的目的是什么,这有什么帮助吗?
与 Adrian Klaver points out in their , and also seen in this answer 一样,问题是 CTE 中的输入丢失了。
我们可以在 psql
shell:
中用一个例子来说明这一点
CREATE TABLE test (col1 json);
WITH cte (c) AS (VALUES ('{"a": 1}'))
INSERT INTO test (col) SELECT c FROM cte;
导致
ERROR: column "col" is of type json but expression is of type text
而具有指定类型的此版本成功:
WITH cte(c) AS (VALUES ('{"a": 1}'::json))
INSERT INTO test (col) SELECT c FROM cte;
我们可以在 execute_values
中通过在模板参数中提供类型信息来模仿这一点:
extras.execute_values(cursor, query, data, template='(%s::json, %s, %s, %s)')
我在 postgres
中有这个 tableCREATE TABLE target (
a json
b integer
c text []
id integer
CONSTRAINT id_fkey FOREIGN KEY (id)
REFERENCES public.other_table(id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
)
我想使用
从 psycopg2 插入数据import psycopg2
import psycopg2.extras as extras
# data is of the form dict, integer, list(string), string <- used to get fkey id
data = [[extras.Json([{'a':1,'b':2}, {'d':3,'e':2}]), 1, ['hello', 'world'], 'ident1'],
[extras.Json([{'a':4,'b':3}, {'d':1,'e':9}]), 5, ['hello2', 'world2'], 'ident2']]
# convert data to list of tuples containing objects
x = [tuple(u) for u in data]
# insert data to the database
query = ('WITH ins (a, b, c, ident) AS '
'(VALUES %s) '
'INSERT INTO target (a, b, c, id) '
'SELECT '
'ins.a '
'ins.b '
'ins.c '
'other_table.id'
'FROM '
'ins '
'LEFT JOIN other_table ON ins.ident = other_table.ident;')
cursor = conn.cursor()
extras.execute_values(cursor, query, x)
当我 运行 这个时,我得到了 error: column "a" is of type json but expression is of type text
。我试图通过在 SELECT 语句中添加类型转换来解决这个问题,但后来我对 c 和 b.
最初我认为问题在于 WITH 语句,但根据我之前问题的答案,情况似乎并非如此
似乎 execute_values
将所有值作为带有 ' '
的文本发送。
主要问题: 我怎样才能让 execute_values
发送基于 python 数据类型的值,而不是仅仅文字?
子问题:
我如何确认 execute_values
实际上是以带引号的文本形式发送值?
execute_values
https://www.psycopg.org/docs/extras.html 的模板参数的目的是什么,这有什么帮助吗?
与 Adrian Klaver points out in their
我们可以在 psql
shell:
CREATE TABLE test (col1 json);
WITH cte (c) AS (VALUES ('{"a": 1}'))
INSERT INTO test (col) SELECT c FROM cte;
导致
ERROR: column "col" is of type json but expression is of type text
而具有指定类型的此版本成功:
WITH cte(c) AS (VALUES ('{"a": 1}'::json))
INSERT INTO test (col) SELECT c FROM cte;
我们可以在 execute_values
中通过在模板参数中提供类型信息来模仿这一点:
extras.execute_values(cursor, query, data, template='(%s::json, %s, %s, %s)')