具有DEFAULT值的多行条件插入

时间:2019-01-17 09:14:58

标签: sql database postgresql insert bulkinsert

这是我要在表中插入多行的PostgreSQL查询的简化版本:

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条件实际上很复杂并且涉及其他表。此外,一次要插入几千行,并以编程方式生成值表达式。可以这样做,以便输出表的文字默认值而不是DEFAULT,但是这需要在数据库外部进行硬编码,这是我要避免的(因为如果在数据库中更改它们而忘记了,更新硬编码的值,将会引起问题。

1 个答案:

答案 0 :(得分:0)

由于我找不到更优雅的东西(如当前缺乏其他答案所证明),我最终使用了将这些值首先插入临时表中的建议。 PostgreSQL使创建具有相同默认值但没有其他一些不必要内容的“克隆”表(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');

然后,只需使用临时表代替之前的VALUES子句即可。

INSERT INTO my_table (a, b, datasource)
SELECT a, b, 'my source'
FROM temp_table
WHERE a = 'foo';

一个小警告是您无法避免将NOT NULL约束复制到临时表中。例如,如果datasource列为NOT NULL(并且没有默认值),则必须在第一个INSERT查询中添加该值(或占位符),或删除列。