Postgres - 使用 INSERT INTO SELECT 语句插入自引用序列记录
Postgres - Insert self referencing sequenced record with INSERT INTO SELECT statement
我一直在尝试将数据插入自引用 table,而数据来自其他不同的 table。该行是一种根记录,需要有自己的引用作为外键。为了更容易理解,在此处提供 table DDL -
CREATE TABLE self_refer (
id SERIAL PRIMARY KEY,
parent_id INTEGER NOT NULL,
FOREIGN KEY (parent_id) REFERENCES self_refer(id)
);
如果我们想使用直接值插入数据,这是一个讨论的话题here,下面的语句很有效。
INSERT INTO self_refer
(parent_id)
VALUES ((SELECT last_value
FROM self_refer_id_seq))
在我的例子中,我需要插入来自其他 table 的数据,因此语句将是 INSERT INTO SELECT
类型。以下是我的尝试,它们没有按预期工作。
INSERT INTO self_refer
(parent_id)
SELECT CURRVAL('self_refer_id_seq')
和
INSERT INTO self_refer
(parent_id)
SELECT last_value
FROM self_refer_id_seq
带有 VALUES
的第一个语句适当地插入数据,但第二个和第三个语句为 last_value
或 currval
提取最新数据。即使与 currval
函数一起使用,第一个查询也能正常工作。
下面是结果,其中前两条记录显示通过 VALUES
插入,后两条记录使用 INSERT INTO SELECT
语句。
id|parent_id|
--|---------|
47| 47|
48| 48|
49| 48|
50| 49|
寻求有关如何实现前两行结果的任何帮助,同时保持 SQL 与后两行相似的语句。
更新:
接受的答案有效,但可能不是理想的解决方案,请通读所有关于如何获得更好解决方案的评论。
添加了以下语句以便更快地访问。如果愿意调整并尝试其他可能性,请随时查看 db fiddle。
CREATE TABLE self_refer (
id SERIAL PRIMARY KEY,
parent_id INTEGER NOT NULL,
FOREIGN KEY (parent_id) REFERENCES self_refer(id)
);
✓
INSERT INTO self_refer
(parent_id)
VALUES ((SELECT last_value
FROM self_refer_id_seq))
1 rows affected
INSERT INTO self_refer
(parent_id)
SELECT CURRVAL('self_refer_id_seq')+1;
1 rows affected
select * from self_refer;
id | parent_id
-: | --------:
1 | 1
2 | 2
INSERT INTO self_refer
(parent_id)
VALUES ((SELECT last_value
FROM self_refer_id_seq))
1 rows affected
select * from self_refer;
id | parent_id
-: | --------:
1 | 1
2 | 2
3 | 3
INSERT INTO self_refer
(parent_id)
SELECT CURRVAL('self_refer_id_seq')+1;
1 rows affected
select * from self_refer;
id | parent_id
-: | --------:
1 | 1
2 | 2
3 | 3
4 | 4
INSERT INTO self_refer
(parent_id)
SELECT last_value +1
FROM self_refer_id_seq
1 rows affected
select * from self_refer;
id | parent_id
-: | --------:
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
insert into self_refer values(default, (currval('self_refer_id_seq')));
1 rows affected
select * from self_refer;
id | parent_id
-: | --------:
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
6 | 6
CREATE FUNCTION my_trigger_function()
RETURNS trigger AS '
BEGIN
IF NEW.parent_id = -1 THEN
NEW.parent_id := NEW.id;
END IF;
return new;
END ' LANGUAGE 'plpgsql'
✓
create trigger test_t
before insert on self_refer
for each row
EXECUTE PROCEDURE my_trigger_function()
✓
INSERT INTO self_refer
(parent_id)
SELECT -1
1 rows affected
select * from self_refer;
id | parent_id
-: | --------:
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
6 | 6
7 | 7
INSERT INTO self_refer
(parent_id)
SELECT 5
1 rows affected
select * from self_refer;
id | parent_id
-: | --------:
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
6 | 6
7 | 7
8 | 5
db<>fiddle here
是否可以这样选择:
INSERT INTO self_refer
(parent_id)
SELECT CURRVAL('self_refer_id_seq')+1;
INSERT INTO self_refer
(parent_id)
SELECT last_value +1
FROM self_refer_id_seq
确实有效:DEMO
更常见的设计将允许列 column parent_id 在顶级父项的情况下为空。这也是一个出色的设计;至少恕我直言。但是
insert into self_refer values(default, (currval('self_refer_id_seq')));
成功了。
我一直在尝试将数据插入自引用 table,而数据来自其他不同的 table。该行是一种根记录,需要有自己的引用作为外键。为了更容易理解,在此处提供 table DDL -
CREATE TABLE self_refer (
id SERIAL PRIMARY KEY,
parent_id INTEGER NOT NULL,
FOREIGN KEY (parent_id) REFERENCES self_refer(id)
);
如果我们想使用直接值插入数据,这是一个讨论的话题here,下面的语句很有效。
INSERT INTO self_refer
(parent_id)
VALUES ((SELECT last_value
FROM self_refer_id_seq))
在我的例子中,我需要插入来自其他 table 的数据,因此语句将是 INSERT INTO SELECT
类型。以下是我的尝试,它们没有按预期工作。
INSERT INTO self_refer
(parent_id)
SELECT CURRVAL('self_refer_id_seq')
和
INSERT INTO self_refer
(parent_id)
SELECT last_value
FROM self_refer_id_seq
带有 VALUES
的第一个语句适当地插入数据,但第二个和第三个语句为 last_value
或 currval
提取最新数据。即使与 currval
函数一起使用,第一个查询也能正常工作。
下面是结果,其中前两条记录显示通过 VALUES
插入,后两条记录使用 INSERT INTO SELECT
语句。
id|parent_id|
--|---------|
47| 47|
48| 48|
49| 48|
50| 49|
寻求有关如何实现前两行结果的任何帮助,同时保持 SQL 与后两行相似的语句。
更新: 接受的答案有效,但可能不是理想的解决方案,请通读所有关于如何获得更好解决方案的评论。
添加了以下语句以便更快地访问。如果愿意调整并尝试其他可能性,请随时查看 db fiddle。
CREATE TABLE self_refer ( id SERIAL PRIMARY KEY, parent_id INTEGER NOT NULL, FOREIGN KEY (parent_id) REFERENCES self_refer(id) );
✓
INSERT INTO self_refer (parent_id) VALUES ((SELECT last_value FROM self_refer_id_seq))
1 rows affected
INSERT INTO self_refer (parent_id) SELECT CURRVAL('self_refer_id_seq')+1;
1 rows affected
select * from self_refer;
id | parent_id -: | --------: 1 | 1 2 | 2
INSERT INTO self_refer (parent_id) VALUES ((SELECT last_value FROM self_refer_id_seq))
1 rows affected
select * from self_refer;
id | parent_id -: | --------: 1 | 1 2 | 2 3 | 3
INSERT INTO self_refer (parent_id) SELECT CURRVAL('self_refer_id_seq')+1;
1 rows affected
select * from self_refer;
id | parent_id -: | --------: 1 | 1 2 | 2 3 | 3 4 | 4
INSERT INTO self_refer (parent_id) SELECT last_value +1 FROM self_refer_id_seq
1 rows affected
select * from self_refer;
id | parent_id -: | --------: 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5
insert into self_refer values(default, (currval('self_refer_id_seq')));
1 rows affected
select * from self_refer;
id | parent_id -: | --------: 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6
CREATE FUNCTION my_trigger_function() RETURNS trigger AS ' BEGIN IF NEW.parent_id = -1 THEN NEW.parent_id := NEW.id; END IF; return new; END ' LANGUAGE 'plpgsql'
✓
create trigger test_t before insert on self_refer for each row EXECUTE PROCEDURE my_trigger_function()
✓
INSERT INTO self_refer (parent_id) SELECT -1
1 rows affected
select * from self_refer;
id | parent_id -: | --------: 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7
INSERT INTO self_refer (parent_id) SELECT 5
1 rows affected
select * from self_refer;
id | parent_id -: | --------: 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 5
db<>fiddle here
是否可以这样选择:
INSERT INTO self_refer
(parent_id)
SELECT CURRVAL('self_refer_id_seq')+1;
INSERT INTO self_refer
(parent_id)
SELECT last_value +1
FROM self_refer_id_seq
确实有效:DEMO
更常见的设计将允许列 column parent_id 在顶级父项的情况下为空。这也是一个出色的设计;至少恕我直言。但是
insert into self_refer values(default, (currval('self_refer_id_seq')));
成功了。