具有 DEFAULT 值的多行条件插入
Multi-row conditional insert with DEFAULT values
这是我拥有的 PostgreSQL 查询的简化版本,用于将多行插入 table:
INSERT INTO my_table (a, b, datasource)
VALUES
('foo', 'bar', 'my source'),
('foo', DEFAULT, 'my source'),
(DEFAULT, 'bar', 'my source');
请注意,DEFAULT
值可能出现在 a
或 b
列中。
这很好用,但是我只想插入满足某些条件的行,另外最好删除重复的值,这些值对所有插入的行都是恒定的。
所以我试着把它改成这样:
INSERT INTO my_table (a, b, datasource)
SELECT v.*, 'my source'
FROM (VALUES ('foo', 'bar'), ('foo', DEFAULT), (DEFAULT, 'bar')) AS v (a, b)
WHERE v.a = 'foo';
这会导致错误:DEFAULT is not allowed in this context
。
我该如何解决这个问题?
可能值得注意的是,在现实中,WHERE
条件实际上很复杂并且涉及其他 table。一次也有几千行要插入,值表达式以编程方式生成。可以让它输出 table 的文字默认值而不是 DEFAULT
,但是这需要在数据库外对它们进行硬编码,我想避免这种情况(因为如果我在数据库而忘记更新硬编码值,这会导致问题)。
由于我找不到更优雅的东西(正如目前缺乏其他答案所证明的那样),我最终使用了将值首先插入临时 table 的建议。 PostgreSQL 使得创建具有相同默认值但没有其他一些不必要的东西的 "clone" table (using the LIKE
keyword) 变得非常容易:
CREATE TEMPORARY TABLE temp_table (
LIKE my_table INCLUDING DEFAULTS
);
INSERT INTO temp_table (a, b)
VALUES
('foo', 'bar'),
('foo', DEFAULT),
(DEFAULT, 'bar');
那么只需使用 temp table 代替之前的 VALUES
子句即可:
INSERT INTO my_table (a, b, datasource)
SELECT a, b, 'my source'
FROM temp_table
WHERE a = 'foo';
一个小警告是您无法避免 NOT NULL
约束被复制到临时 table。例如,如果 datasource
列是 NOT NULL
(并且没有默认值),我必须在第一个 INSERT
查询中添加值(或占位符),或删除该列。
这是我拥有的 PostgreSQL 查询的简化版本,用于将多行插入 table:
INSERT INTO my_table (a, b, datasource)
VALUES
('foo', 'bar', 'my source'),
('foo', DEFAULT, 'my source'),
(DEFAULT, 'bar', 'my source');
请注意,DEFAULT
值可能出现在 a
或 b
列中。
这很好用,但是我只想插入满足某些条件的行,另外最好删除重复的值,这些值对所有插入的行都是恒定的。
所以我试着把它改成这样:
INSERT INTO my_table (a, b, datasource)
SELECT v.*, 'my source'
FROM (VALUES ('foo', 'bar'), ('foo', DEFAULT), (DEFAULT, 'bar')) AS v (a, b)
WHERE v.a = 'foo';
这会导致错误:DEFAULT is not allowed in this context
。
我该如何解决这个问题?
可能值得注意的是,在现实中,WHERE
条件实际上很复杂并且涉及其他 table。一次也有几千行要插入,值表达式以编程方式生成。可以让它输出 table 的文字默认值而不是 DEFAULT
,但是这需要在数据库外对它们进行硬编码,我想避免这种情况(因为如果我在数据库而忘记更新硬编码值,这会导致问题)。
由于我找不到更优雅的东西(正如目前缺乏其他答案所证明的那样),我最终使用了将值首先插入临时 table 的建议。 PostgreSQL 使得创建具有相同默认值但没有其他一些不必要的东西的 "clone" table (using the LIKE
keyword) 变得非常容易:
CREATE TEMPORARY TABLE temp_table (
LIKE my_table INCLUDING DEFAULTS
);
INSERT INTO temp_table (a, b)
VALUES
('foo', 'bar'),
('foo', DEFAULT),
(DEFAULT, 'bar');
那么只需使用 temp table 代替之前的 VALUES
子句即可:
INSERT INTO my_table (a, b, datasource)
SELECT a, b, 'my source'
FROM temp_table
WHERE a = 'foo';
一个小警告是您无法避免 NOT NULL
约束被复制到临时 table。例如,如果 datasource
列是 NOT NULL
(并且没有默认值),我必须在第一个 INSERT
查询中添加值(或占位符),或删除该列。