在Postgresql中插入自引用记录

Ovi*_*vid 10 postgresql

鉴于PostgreSQL中的下表,如何插入引用自身的记录?

CREATE TABLE refers (
    id        SERIAL  PRIMARY KEY,
    name      VARCHAR(255) NOT NULL,
    parent_id INTEGER      NOT NULL,
    FOREIGN KEY (parent_id) REFERENCES refers(id)
);
Run Code Online (Sandbox Code Playgroud)

我在Web上找到的示例允许parent_id为NULL,然后使用触发器来更新它.如果可能的话,我宁愿一次更新.

wic*_*ich 14

您可以从序列中选择last_value,即使用类型serial时自动创建的:

create table test (
  id serial primary key,
  parent integer not null,
  foreign key (parent) references test(id)
);

insert into test values(default, (select last_value from test_id_seq));
insert into test values(default, (select last_value from test_id_seq));
insert into test values(default, (select last_value from test_id_seq));

select * from test;
 id | parent
----+--------
  1 |      1
  2 |      2
  3 |      3
(3 rows)
Run Code Online (Sandbox Code Playgroud)

以下甚至更简单似乎也可以工作:

insert into test values(default, lastval());
Run Code Online (Sandbox Code Playgroud)

虽然我不知道在使用多个序列时这是如何工作的......我查了一下; lastval()返回最后一个返回值或使用最后一个nextval或setval调用设置任何序列,因此以下内容会让您遇到麻烦:

create table test (
  id serial primary key,
  foo serial not null,
  parent integer not null,
  foreign key (parent) references test(id)
);

select setval('test_foo_seq', 100);

insert into test values(default, default, lastval());
ERROR:  insert or update on table "test" violates foreign key constraint "test_parent_fkey"
DETAIL:  Key (parent)=(101) is not present in table "test".
Run Code Online (Sandbox Code Playgroud)

但是以下情况可以:

insert into test values(default, default, currval('test_id_seq'));

select * from test;
 id | foo | parent
----+-----+--------
  2 | 102 |      2
(1 row)
Run Code Online (Sandbox Code Playgroud)