我正在尝试使用虚拟数据生成虚拟表,以测试某些 SQL 任务的性能。
基于这个旧线程:有没有办法将多行插入到所有列的默认值的表中?
我注意到,对于一个IDENTITY
类型,使用建议的generate_series(1, N)
解决方案不再可能用虚拟数据填充表。
那么,我如何将 1'000 个虚拟数据插入到例如下表 (PG 14) 中,利用该字段的默认值name
而不覆盖该字段的系统值id
:
CREATE TABLE foo (
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name TEXT DEFAULT md5(random()::text)
);
尝试以下失败:
INSERT INTO foo (id)
SELECT generate_series(1, 1000);
-- which results in:
ERROR: cannot insert a non-DEFAULT value into column "id"
DETAIL: Column "id" is an identity column defined as GENERATED ALWAYS.
HINT: Use OVERRIDING SYSTEM VALUE to override.
SQL state: 428C9
作为一种解决方法,我现在正在创建一个带有额外字段的表,以便i
简单INTEGER
地提供这个字段,而不是id
在插入数据后将其删除,但它对我来说并不是 100% 干净的。
我希望有一些简单明了的东西,例如:
INSERT INTO foo DEFAULT VALUES (1000);
但这显然是一种无效的语法。
即使所有列都具有默认表达式也可以使用的另一种方法是提供一个列并使用
OVERRIDING USER VALUE
选项中的选项INSERT
以忽略那些提供的值。在dbfiddle.uk (1)中测试
使用的另一种方法
MERGE
- 仅在 Postgres 版本 15(下个月发布)中可用。感谢 Paul White 为 SQL Server 和 Martin Smith 和 AndriyM 找到了类似问题的答案:IDENTITY
列的表中在这里重写了 Postgres 的必要更改并在dbfiddle.uk (2)中进行了测试:
(希望说明已更新)
如果我们可以提供一个 0 列表作为输入,但这还没有实现,这将是很好的——
select
它可以自己工作,但不能insert into foo ()
:但这从 9.4 版开始有效。诀窍是使用
insert into foo
- 没有()
- 它接受具有任意列数的输入表(从零到表的列数):在dbfiddle.uk (3)中测试所有三种方法:
或者
小提琴