4

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[]
);

そして、SQLで示されているが、PythonPsycopg2から次の挿入を実行したいと思います。

insert into posts(body,q) VALUES('ninjas rock',ARRAY[ ROW('I AGREE',True)::quotes, ROW('I DISAGREE',FALSE)::quotes ]);

これを実現するための構文は何ですか(ループなどなし)。ドキュメントには 「バージョン2.4.3で変更:複合型の配列のサポートが追加されました」と記載されているので、それは可能だと確信しています。ドキュメントには、SELECTステートメントの例のみが示されています。

注:クライアントコードには、上記の疑似スキーマに概念的にマップするdictのリストがあります。

編集:

うーん、私はドキュメントからこれを見逃したに違いありません:「Pythonタプルから複合型への適応は代わりに自動であり、アダプターの登録は必要ありません。」。次に、配列部分を理解します。

編集2:

psycopg2の%sプレースホルダーは、渡されるデータ型がまたはの場合に機能するはずlist(tuple)ですlist(dict)。テストする必要があります:D

edit3:わかり ました。このシナリオでは、dictは機能せず、リストは機能し、タプルは機能します。ただし、タプル文字列表現を複合レコード型にキャストする必要があります。

これ :

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))

次の文字列を作成します。

insert into posts VALUES('animals are good',ARRAY[('monkeys rock', 'false'), ('donkeys rock', 'true')])

これにより、次のエラーが発生します。

psycopg2.ProgrammingError: column "q" is of type quotes[] but expression is of type record[]
4

1 に答える 1

6

少しだけ努力を広げてみてはいかがでしょうか。

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[]->^^^^^^^^

説明

実行する場合:

insert into posts 
VALUES('animals are good', ARRAY[
    ('monkeys rock', 'false'),
    ('donkeys rock', 'true')
]);

直接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.

案の定、匿名配列がタイプであることを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)
于 2012-08-15T01:30:16.657 に答える