简体   繁体   English

具有DEFAULT值的多行条件插入

[英]Multi-row conditional insert with DEFAULT values

Here is a simplified version of a PostgreSQL query I have, to insert multiple rows into a table: 这是我要在表中插入多行的PostgreSQL查询的简化版本:

INSERT INTO my_table (a, b, datasource)
VALUES
  ('foo', 'bar', 'my source'),
  ('foo', DEFAULT, 'my source'),
  (DEFAULT, 'bar', 'my source');

Notice that a DEFAULT value could appear in either column a or b . 注意, DEFAULT值可能出现在ab列中。

That works fine, however I only want to insert rows that meet some criteria, and additionally it would be nice to remove the duplication for values that are constant for all the rows that are being inserted. 这样做很好,但是我只想插入满足某些条件的行,此外,删除重复的值对于所有要插入的行都是恒定的,这将是很好的。

So I try to change it to something like this: 因此,我尝试将其更改为以下内容:

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';

This results in the error: DEFAULT is not allowed in this context . 这导致错误: DEFAULT is not allowed in this context

How do I work around this? 我该如何解决?

It might be worth noting that in reality, the WHERE condition is actually complex and involves other tables. 可能值得注意的是,实际上, WHERE条件实际上很复杂,并且涉及其他表。 Also there are several thousand rows to insert at a time, with the value expressions being programmatically generated. 此外,一次要插入几千行,并以编程方式生成值表达式。 It is possible to make it so that the literal default values for the table are output instead of DEFAULT , however that requires hardcoding them outside the database, which I want to avoid (because if I change them in the DB and forget to update the hardcoded values, it will cause issues). 可以这样做,以便输出表的字面默认值而不是DEFAULT ,但是这需要在数据库之外对它们进行硬编码,这是我想避免的(因为如果我在数据库中更改了它们而忘记更新硬编码的话)值,将导致问题)。

Since I couldn't find anything more elegant (as evidenced by the current lack of other answers) I ended up using the suggestion to insert the values into a temporary table first. 由于找不到任何更优雅的方法(如当前缺乏其他答案所证明),我最终使用了建议,首先将值插入到临时表中。 PostgreSQL makes it really easy to create a "clone" table ( using the LIKE keyword ) with the same default values but without some of the other unnecessary stuff: PostgreSQL使使用相同的默认值创建一个“克隆”表( 使用LIKE关键字 )变得非常容易,但没有其他一些不必要的东西:

CREATE TEMPORARY TABLE temp_table (
  LIKE my_table INCLUDING DEFAULTS
);

INSERT INTO temp_table (a, b)
VALUES
  ('foo', 'bar'),
  ('foo', DEFAULT),
  (DEFAULT, 'bar');

Then it's just a matter of using the temp table in place of the VALUES clause from before: 然后,只需使用临时表代替之前的VALUES子句即可:

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

One small caveat is that you can't avoid NOT NULL constraints from being copied to the temporary table. 一个小警告是您无法避免将NOT NULL约束复制到临时表中。 For example, if the datasource column was NOT NULL (and didn't have a default value), I would have to add the value (or a placeholder) in the first INSERT query, or drop the column. 例如,如果datasourceNOT NULL (并且没有默认值),则必须在第一个INSERT查询中添加值(或占位符),或删除该列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM