具有 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 值可能出现在 ab 列中。

这很好用,但是我只想插入满足某些条件的行,另外最好删除重复的值,这些值对所有插入的行都是恒定的。

所以我试着把它改成这样:

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 查询中添加值(或占位符),或删除该列。