最终版本
...从OP获得更多信息后。考虑这个演示:
-- DROP TABLE foo; DROP TABLE bar;
CREATE TEMP TABLE bar (
id serial PRIMARY KEY -- using a serial column!
, z integer NOT NULL
);
CREATE TEMP TABLE foo (
id serial PRIMARY KEY -- using a serial column!
, x integer NOT NULL
, y integer NOT NULL
, bar_id integer UNIQUE NOT NULL REFERENCES bar(id)
);
插入值 -bar
first.
像这样的测试数据对您的问题非常有帮助:
INSERT INTO bar (id,z) VALUES
(100, 7)
, (101,16)
, (102,21)
;
INSERT INTO foo (id, x, y, bar_id) VALUES
(1, 3,4,100)
, (2, 9,6,101)
, (3,18,0,102)
;
将序列设置为当前值,否则我们会得到重复的键违规:
SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);
Checks:
-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;
Query:
WITH a AS (
SELECT f.x, f.y, bar_id, b.z
FROM foo f
JOIN bar b ON b.id = f.bar_id
WHERE x > 3
),b AS (
INSERT INTO bar (z)
SELECT z
FROM a
RETURNING z, id AS bar_id
)
INSERT INTO foo (x, y, bar_id)
SELECT a.x, a.y, b.bar_id
FROM a
JOIN b USING (z);
这应该执行您上次更新所描述的操作。
该查询假设z
is UNIQUE
. If z
并不独特,它变得更加复杂。参考此相关答案中的查询 2 https://stackoverflow.com/a/10201349/939860使用窗口函数的现成解决方案row_number()
在这种情况下。
另外,请考虑更换1:1关系之间foo
and bar
与一个统一的表。
数据修改CTE
更多信息后的第二个答案。
如果您想添加行foo
and bar
在单个查询中,您可以使用数据修改CTE https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-MODIFYING自从 PostgreSQL9.1:
WITH x AS (
INSERT INTO bar (col1, col2)
SELECT f.col1, f.col2
FROM foo f
WHERE f.id BETWEEN 12 AND 23 -- some filter
RETURNING col1, col2, bar_id -- assuming bar_id is a serial column
)
INSERT INTO foo (col1, col2, bar_id)
SELECT col1, col2, bar_id
FROM x;
我从中获取价值观foo
,将它们插入bar
,让它们与自动生成的一起返回bar_id
并插入that into foo
。您也可以使用任何其他数据。
这里有一个在 sqlfiddle 上玩的工作演示 http://sqlfiddle.com/#!1/5a52c/1.
Basics
原始答案在澄清之前包含基本信息。
基本形式是:
INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...
不需要括号。
您可以对任何表执行相同的操作
INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...
您可以连接到在 SELECT 中插入的表:
INSERT INTO foo (...)
SELECT f.col1, f.col2, .. , b.bar_id
FROM foo f
JOIN bar b USING (foo_id); -- present in foo and bar
这只是一个SELECT
与其他任何表一样 - 可以包括您要插入的表。首先读取行,然后插入。