在Postgresql中插入自引用记录

时间:2010-01-24 13:11:43

标签: 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)
);

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

2 个答案:

答案 0 :(得分:10)

您可以从序列中选择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)

以下更简单似乎也有效:

insert into test values(default, lastval());

虽然我不知道在使用多个序列时这是如何工作的......我查了一下; 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".

但是以下情况可以接受:

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

select * from test;
 id | foo | parent
----+-----+--------
  2 | 102 |      2
(1 row)

答案 1 :(得分:2)

主要问题是 - 你为什么要插入与自身相关的记录?

Schema看起来像标准邻接列表 - 在关系数据库中实现树的方法之一。

事实上,在大多数情况下,您只需要为顶级元素使用parent_id NULL 。这实际上更容易处理。