Postgres 将数据插入复合类型 [duplicate]

Postgres insert data into composite type [duplicate]

提问人:Niranjan 提问时间:11/12/2023 最后编辑:marc_sNiranjan 更新时间:11/13/2023 访问量:56

问:

我在Postgres工作。我有以下复合类型

CREATE TYPE negotiation.diff_type AS 
(
    operation int,
    content text
);

这是我的桌子

CREATE temp TABLE temp_input 
(
    indication_request_id int, 
    para_id int, 
    line_number int, 
    document_id int, 
    modified_content text, 
    created_by text, 
    diffs diff_type[]
);

在表中,我使用的是 diffs 复合类型。

下面我将数据插入到表中。

INSERT INTO temp_input (myid, para_id, line_number, document_id,modified_content,created_by, diffs)
VALUES (20,2893,10,18,'my content','user1', '{(1,"DDD")"}');

我收到此错误:

错误:格式错误的数组文本:“{(1,”DDD“)”}”

SQL 数组 postgresql 语法错误 复合类型

评论

1赞 Laurenz Albe 11/12/2023
我的建议是永远不要使用复合类型作为列数据类型。它增加了不必要的复杂性。此外,它看起来很像您实际尝试建模的是两个实体之间的 1:n 关系。为此,请使用两个带有外键的表。这将使您的查询更简单,性能也会更好。

答:

3赞 Mureinik 11/12/2023 #1

您需要用引号将数组的每个元素括起来,然后转义复杂类型文本中的引号:

INSERT INTO temp_input
(indication_request_id, para_id, line_number, document_id,modified_content,created_by, diffs)
VALUES (20,2893,10,18,'my content','user1', '{"(1,\"DDD\")"}');

SQLFiddle 演示

评论

0赞 Niranjan 11/12/2023
嗨,谢谢你的回答。如果必须将多行插入到差异中,则格式是什么
0赞 Mureinik 11/12/2023
@Niranjan 您的意思是表中的几行还是同一行中的几个差异?
0赞 Niranjan 11/13/2023
同一行中的多个差异
3赞 Jonathan Jacobson 11/12/2023 #2

这就是你如何创建一个包含数组的文字:negotiation.diff_type

array['(1,abc)','(2,def)']::negotiation.diff_type[]
1赞 Erwin Brandstetter 11/13/2023 #3

概念验证

演示命令的正确语法是:

INSERT INTO temp_input (indication_request_id, para_id, line_number, document_id,modified_content,created_by, diffs)
VALUES (20,2893,10,18,'my content','user1', '{"(1,DDD)"}');

具有多个数组元素的多个输入行的正确语法:

INSERT INTO temp_input (indication_request_id, para_id, line_number, document_id,modified_content,created_by, diffs)
VALUES
  (2,3,10,18,'my content','user1', '{"(1,DDD)","(2,foo)"}')
, (3,4,10,18,'my content','user1', '{"(1,DDD)","(2,foo)","(3,\"Weird \\\\string\"\"\")"}')
;

只需向 Postgres 询问正确的语法(psql 摘录):

test=> BEGIN;
BEGIN
test=*> CREATE TYPE diff_type AS (
test(*>     operation int,
test(*>     content text
test(*> );
CREATE TYPE
test=*> CREATE TEMP TABLE syntax_demo OF diff_type;
CREATE TABLE
test=*> INSERT INTO syntax_demo VALUES
test-*>   (1, 'DDD')
test-*> , (2, 'foo')
test-*> , (3, 'Weird \string"');
INSERT 0 3
test=*> 
test=*> SELECT ARRAY(SELECT t FROM syntax_demo t) AS proper_syntax;
                    proper_syntax                     
------------------------------------------------------
 {"(1,DDD)","(2,foo)","(3,\"Weird \\\\string\"\"\")"}   -- !!!
(1 row)

test=*> ROLLBACK;

测试:

SELECT '{"(1,DDD)","(2,foo)","(3,\"Weird \\\\string\"\"\")"}'::diff_type[];

反向测试:

SELECT (('{"(1,DDD)","(2,foo)","(3,\"Weird \\\\string\"\"\")"}'::diff_type[])[3]).content;

小提琴
(请注意当前有缺陷的显示 dbfiddle.uk:它吞噬了转义的内部级别。
\

如您所见,您需要在每行文字(= 复合元素类型)周围括起双引号,但不要在嵌套字符串周围括起来,除非它包含特殊字符。然后你必须摆脱这些,在这一点上,多层嵌套很快就会变得混乱。只需让 Postgres 为您完成即可。

看:

更好的是

不要一开始就去那里。正如 Laurenz 所评论的那样,表定义中的复合数据类型通常表明对正确的数据库设计存在误解。考虑一个半途而废的规范化架构。