有没有一种方法可以将多个行插入到具有所有列默认值的表中?


14

我可以使用RBAR方式将所有行的默认值插入表中的多行:

create table course(course_id serial primary key);

do $$
begin
  for i in 1..100000 loop
    insert into course default values;
  end loop;
end;$$;

有没有办法对单个SQL语句执行相同的操作?


广泛的答案在SO密切相关的问题:stackoverflow.com/questions/23794405/...
欧文Brandstetter修改

Answers:


8

使用generate_series()和ctes。在rextester.com中测试过:

create table t
( tid serial primary key,
  i int default 0,
  name text default 'Jack'
) ;


with ins as
  (insert into t (i, name)               -- all the columns except any serial
   values (default, default)
   returning i, name
  )
insert into t 
  (i, name)
select 
  ins.i, ins.name
from 
  ins cross join generate_series(1, 9);  -- one less than you need

对于只有一列而只有一列的情况serial,我看不到使用的方法default。使用generate_series很简单:

insert into course
  (course_id)
select
  nextval('course_course_id_seq')
from
  generate_series(1, 10);

  • 如果还有其他更多的“特殊”默认值(例如UUID函数或非标准)clock_timestamp(),则必须像串行情况一样,对语句进行相应的调整。

如果主键不是定义的“第一列”列,那么在本例中,如果i首先定义了主键,那么您可以使用一个更简单的版本,例如INSERT INTO t SELECT * FROM generate_series(1, 10)基本上分配给第一列并为所有其余列提供默认值,找不到其他简单的方法。如果只是一次,那么您也可以首先使用主键进行操作,例如,通过生成一系列值,您将“可能永远不会重复使用”,例如:INSERT INTO t SELECT * FROM generate_series(1000000, 1000000+10)然后手动更改数字。
rogerdpack '16

当我在SQL Fiddle中运行它时,第一个查询没有在table中插入任何行t。我没有正确使用SQL Fiddle吗?
德里克·马哈尔

我现在知道我做错了。SQL Fiddle将每个执行都视为一个事务,完成后会回滚。因此,为了查看表中的行,我必须select * from t在CTE语句之后执行。
德里克·马哈尔

不,那也不起作用。
德里克·马哈尔

1
@DerekMahar SQLfiddle必须损坏。我已经编辑了指向rextester.com的链接。
ypercubeᵀᴹ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.