INSERT SELECT FROM VALUES cast

时间:2017-11-28 16:05:09

标签: sql postgresql sql-types

通常需要从SELECT表达式INSERT(例如,使用WHERE子句限定),但这可能会使postgresql对列类型感到困惑。

示例:

CREATE TABLE example (a uuid primary key, b numeric);
INSERT INTO example 
SELECT a, b 
FROM (VALUES ('d853b5a8-d453-11e7-9296-cec278b6b50a', NULL)) as data(a,b);
=> ERROR:  column "a" is of type uuid but expression is of type text

这可以通过显式地转换值来修复:

INSERT INTO example 
SELECT a, b 
FROM (VALUES ('d853b5a8-d453-11e7-9296-cec278b6b50a'::uuid, NULL::numeric)) as data(a,b);

但这很麻烦,也有维护负担。有没有办法使postgres明白VALUES表达式与表行具有相同的类型,例如

VALUES('d853b5a8-d453-11e7-9296-cec278b6b50a', NULL)::example%ROWTYPE

编辑:

使用(data :: example)。*的建议很简洁,但遗憾的是,当与WHERE子句结合使用时,它完全似乎搞砸了postgres查询规划器:

INSERT INTO example 
SELECT (data::example).* 
FROM (VALUES ('d853b5a8-d453-11e7-9296-cec278b6b50a', NULL)) as data 
WHERE NOT EXISTS (SELECT * FROM example 
                  WHERE (data::example) 
                  IS NOT DISTINCT FROM example);

使用大桌子需要几分钟。

2 个答案:

答案 0 :(得分:4)

可以将记录转换为表格的行类型:

INSERT INTO example 
SELECT (data::example).*
FROM (
    VALUES 
      ('d853b5a8-d453-11e7-9296-cec278b6b50a', NULL),
      ('54514c89-f188-490a-abbb-268f9154ab2c', 42)
) as data;

data::example将完整行强制转换为example类型的记录。 (...).*然后将其转换为表格类型example

中定义的列

答案 1 :(得分:2)

您可以直接使用SHOW COLUMNS FROM `table name`

VALUES

<强> DBFiddle Demo

或者只是施放一次:

INSERT INTO example(a, b)
VALUES ('d853b5a8-d453-11e7-9296-cec278b6b50a', NULL);

<强> DBFiddle Demo2

注意,请始终明确定义列表。