Has*_*yed 4 python postgresql orm psycopg2 relational-database
Postgres版本:9.1.x。
说我有以下架构:
DROP TABLE IF EXISTS posts CASCADE;
DROP TYPE IF EXISTS quotes CASCADE;
CREATE TYPE quotes AS
(
text CHARACTER VARYING,
is_direct CHARACTER VARYING
);
CREATE TABLE posts
(
body CHARACTER VARYING,
q quotes[]
);
Run Code Online (Sandbox Code Playgroud)
我希望执行以下插入操作(以SQL所示),但是要从Python Psycopg2执行。
insert into posts(body,q) VALUES('ninjas rock',ARRAY[ ROW('I AGREE',True)::quotes, ROW('I DISAGREE',FALSE)::quotes ]);
Run Code Online (Sandbox Code Playgroud)
实现此目的的语法是什么(没有循环等)。我确信这是可能的,因为该文档说 “在2.4.3版中进行了更改:增加了对复合类型数组的支持”。该文档仅显示SELECT语句示例。
注意:我的客户端代码中有一系列字典,这些字典在概念上映射到上面的psuedo模式。
编辑:
嗯,我一定从文档中错过了这一点:“相反,从Python元组到复合类型的自适应是自动的,不需要适配器注册。” 。现在找出阵列部分。
编辑2:
%s当传递的数据类型为list(tuple)或时,psycopg2的占位符应起作用list(dict)。要测试一下:D
edit3: 好的,在这种情况下,字典不起作用,列表起作用,而元组起作用。但是,我需要将元组字符串表示形式转换为复合记录类型。
这个 :
quote_1 = ("monkeys rock", "False")
quote_2 = ("donkeys rock", "True")
q_list = [ quote_1, quote_2]
print cur.mogrify("insert into posts VALUES(%s,%s)", ("animals are good", q_list))
Run Code Online (Sandbox Code Playgroud)
创建以下字符串:
insert into posts VALUES('animals are good',ARRAY[('monkeys rock', 'false'), ('donkeys rock', 'true')])
Run Code Online (Sandbox Code Playgroud)
产生以下错误:
psycopg2.ProgrammingError: column "q" is of type quotes[] but expression is of type record[]
Run Code Online (Sandbox Code Playgroud)
稍加努力,如何:
quote_1 = ("monkeys rock", "False")
quote_2 = ("donkeys rock", "True")
q_list = [ quote_1, quote_2]
print cur.mogrify("insert into posts VALUES(%s,%s::quotes[])",
("animals are good", q_list))
#
# added explicit cast to quotes[]->^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
说明:
如果您运行:
insert into posts
VALUES('animals are good', ARRAY[
('monkeys rock', 'false'),
('donkeys rock', 'true')
]);
Run Code Online (Sandbox Code Playgroud)
直接进入psql您将获得:
regress=# insert into posts
regress-# VALUES('animals are good',ARRAY[
regress-# ('monkeys rock', 'false'),
regress-# ('donkeys rock', 'true')
regress-# ]);
ERROR: column "q" is of type quotes[] but expression is of type record[]
LINE 1: insert into posts VALUES('animals are good',ARRAY[('monkeys ...
^
HINT: You will need to rewrite or cast the expression.
Run Code Online (Sandbox Code Playgroud)
果然,告诉Pg您的匿名数组是类型的,quotes[]就可以做到:
regress=# insert into posts
regress-# VALUES('animals are good',ARRAY[
regress-# ('monkeys rock', 'false'),
regress-# ('donkeys rock', 'true')
regress-# ]::quotes[]);
INSERT 0 1
regress=# select * from posts;
body | q
------------------+--------------------------------------------------------
animals are good | {"(\"monkeys rock\",false)","(\"donkeys rock\",true)"}
(1 row)
Run Code Online (Sandbox Code Playgroud)