Вставить выбрать из приведения значений
Часто желательно вставлять из выражения SELECT (например, чтобы квалифицировать предложение 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).* аккуратно, но, к сожалению, это полное, кажется, портит планировщик запросов postgres в сочетании с предложением WHERE, таким как:
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 ответа:
Вы можете привести запись к типу строки вашей таблицы:
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
Вы можете использовать
VALUES
напрямую:INSERT INTO example(a, b) VALUES ('d853b5a8-d453-11e7-9296-cec278b6b50a', NULL);
Или просто бросьте один раз:
INSERT INTO example(a, b) SELECT a::uuid, b::numeric FROM (VALUES ('d853b5a8-d453-11e7-9296-cec278b6b50a', NULL), ('bb53b5a8-d453-11e7-9296-cec278b6b50a',1) ) as data(a,b);
Примечание, пожалуйста, всегда явно определяйте список столбцов.