[英]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
值可能出现在a
或b
列中。
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. 例如,如果
datasource
列NOT NULL
(并且没有默认值),则必须在第一个INSERT
查询中添加值(或占位符),或删除该列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.