将虚拟数据插入到具有主键整数字段 GENERATED ALWAYS AS IDENTITY 的空表中

s.k*_*s.k 3 postgresql default-value

我正在尝试使用虚拟数据生成虚拟表,以测试某些 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)
);
Run Code Online (Sandbox Code Playgroud)

尝试以下操作失败:

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
Run Code Online (Sandbox Code Playgroud)

作为一种解决方法,我现在创建一个带有额外字段的表,i以便简单地INTEGER提供该字段id,而不是在数据插入后将其删除,但对我来说它并不是 100% 干净。

我希望有一些简单明了的东西,例如:

INSERT INTO foo DEFAULT VALUES (1000);
Run Code Online (Sandbox Code Playgroud)

但这显然是无效的语法。

ype*_*eᵀᴹ 5

即使所有列都有默认表达式也可以使用的另一种方法是提供一个列并使用OVERRIDING USER VALUE中的选项INSERT来忽略那些提供的值。

insert into foo (id)
  OVERRIDING USER VALUE
select null
from generate_series(1, 10) as gs(i) ;
Run Code Online (Sandbox Code Playgroud)

在 dbfiddle.uk 中测试(1)


另一种方法使用MERGE- 仅在 Postgres 版本 15 中可用(下个月发布)。感谢 Paul White 找到了 SQL Server 的类似问题以及 Martin Smith 和 AndriyM 的答案:

在这里重写,并对 Postgres 进行必要的更改,并在dbfiddle.uk (2)中进行测试:

MERGE INTO
  foo AS tgt
USING
  generate_series(1, 10) AS src  -- << use your source row set here
ON
  FALSE
WHEN NOT MATCHED THEN
  INSERT DEFAULT VALUES
;
Run Code Online (Sandbox Code Playgroud)

(希望注释已更新)
如果我们可以提供一个 0 列表作为输入,那就太好了,但这还没有实现 -select它本身可以工作,但不能insert into foo ()

insert into foo ()
select
from generate_series(1, 10) as gs(i) ;
Run Code Online (Sandbox Code Playgroud)

但从9.4 版本开始就可以了。技巧是使用insert into foo- 不带()- ,它接受具有任意列数的输入表(从零到表的列数):

insert into foo
select
from generate_series(1, 10) as gs(i) ;
Run Code Online (Sandbox Code Playgroud)

测试dbfiddle.uk (3)中的所有三种方法:

select version();
Run Code Online (Sandbox Code Playgroud)
版本
x86_64-pc-linux-gnu 上的 PostgreSQL 15beta3,由 gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-10) 编译,64 位
SELECT 1
Run Code Online (Sandbox Code Playgroud)
CREATE TABLE foo (
    id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    name TEXT DEFAULT md5(random()::text)
);
Run Code Online (Sandbox Code Playgroud)
CREATE TABLE
Run Code Online (Sandbox Code Playgroud)
insert into foo (id)
  OVERRIDING USER VALUE
select null
from generate_series(1, 3) as gs(i) ;   -- add 3 rows

select * from foo ;
Run Code Online (Sandbox Code Playgroud)
INSERT 0 3
Run Code Online (Sandbox Code Playgroud)
ID 姓名
1 08a153d31bafbef82d67c63b959ede87
2 5295cbb135445f954616fbf18031097a
3 5997bfd8e71c09bf244104797369c573
SELECT 3
Run Code Online (Sandbox Code Playgroud)
MERGE INTO
  foo AS tgt
USING
  generate_series(1, 5) AS src   -- add 5 more rows
ON
  FALSE
WHEN NOT MATCHED THEN
  INSERT DEFAULT VALUES ;

select * from foo ;
Run Code Online (Sandbox Code Playgroud)
MERGE 5
Run Code Online (Sandbox Code Playgroud)
ID 姓名
1 08a153d31bafbef82d67c63b959ede87
2 5295cbb135445f954616fbf18031097a
3 5997bfd8e71c09bf244104797369c573
4 73c644ac045b8dbdb4b17b2fb624538a
5 fb0ddc243709b3e3629838268ba5407f
6 af517dc84cb68ac0a5bd8c0cd2ef2ba5
7 fe33bf8a25bce0dbae0e8b80ff23af97
8 e35566ed57b7e0fe70878a03319fbb52
SELECT 8
Run Code Online (Sandbox Code Playgroud)

或者

MERGE INTO
  foo AS tgt
USING
  generate_series(1, 5) AS src   -- add 5 more rows
ON
  FALSE
WHEN NOT MATCHED THEN   
  INSERT (id) VALUES (DEFAULT);
Run Code Online (Sandbox Code Playgroud)
insert into foo
select
from generate_series(1, 2) as gs(i) ;

select * from foo ;
Run Code Online (Sandbox Code Playgroud)
INSERT 0 2
Run Code Online (Sandbox Code Playgroud)
ID 姓名
1 08a153d31bafbef82d67c63b959ede87
2 5295cbb135445f954616fbf18031097a
3 5997bfd8e71c09bf244104797369c573
4 73c644ac045b8dbdb4b17b2fb624538a
5 fb0ddc243709b3e3629838268ba5407f
6 af517dc84cb68ac0a5bd8c0cd2ef2ba5
7 fe33bf8a25bce0dbae0e8b80ff23af97
8 e35566ed57b7e0fe70878a03319fbb52
9 6c71ffb4347d6593358cda63e802ae5e
10 a07ab009a6838533df51b02ca24d26fe
SELECT 10
Run Code Online (Sandbox Code Playgroud)

小提琴