fol*_*ldl 17 sql postgresql insert common-table-expression
我有两个以下表格的表格(即每个foo都链接到一个条形图).
CREATE TABLE foo (
id INTEGER PRIMARY KEY,
x INTEGER NOT NULL,
y INTEGER NOT NULL,
...,
bar_id INTEGER UNIQUE NOT NULL,
FOREIGN key (bar_id) REFERENCES bar(id)
);
CREATE TABLE bar (
id INTEGER PRIMARY KEY,
z INTEGER NOT NULL,
...
);
Run Code Online (Sandbox Code Playgroud)
foo使用嵌套查询复制满足特定条件的行很容易:
INSERT INTO foo (...) (SELECT ... FROM foo WHERE ...)
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何bar为每一行制作相关行的副本foo并将id bar插入新foo行.有没有办法在单个查询中执行此操作?
期望结果的具体例子:
-- Before query:
foo(id=1,x=3,y=4,bar_id=100) ..... bar(id=100,z=7)
foo(id=2,x=9,y=6,bar_id=101) ..... bar(id=101,z=16)
foo(id=3,x=18,y=0,bar_id=102) ..... bar(id=102,z=21)
-- Query copies all pairs of foo/bar rows for which x>3:
-- Originals
foo(id=1,x=3,y=4,bar_id=101) ..... bar(id=101,z=7)
foo(id=2,x=9,y=6,bar_id=102) ..... bar(id=102,z=16)
foo(id=3,x=18,y=0,bar_id=103) ..... bar(id=103,z=21)
-- "Copies" of foo(id=2,...) and foo(id=3,...), with matching copies of
-- bar(id=102,...) and bar(id=103,...)
foo(id=4,x=9,y=6,bar_id=104) ..... bar(id=104,z=16)
foo(id=5,x=18,y=0,bar_id=105) ..... bar(id=105,z=21)
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 29
...来自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)
);
Run Code Online (Sandbox Code Playgroud)
插入值 - bar首先.如果你在这样的问题中提供测试数据
会非常有用!
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);
Run Code Online (Sandbox Code Playgroud)
将序列设置为当前值或我们得到重复的密钥违规:
SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);
Run Code Online (Sandbox Code Playgroud)
检查:
-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;
Run Code Online (Sandbox Code Playgroud)
查询:
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);
Run Code Online (Sandbox Code Playgroud)
这应该是您上次更新描述的内容.
该查询假设z是UNIQUE.如果z不是唯一的,它会变得更加复杂.在这种情况下,请参阅此相关答案中的查询2以获得使用窗口函数的就绪解决方案row_number().
此外,考虑更换1:1的关系之间foo,并bar与一个统一的表格.
更多信息后的第二个答案.
如果你想将行添加到foo ,并 bar在一个单一的查询,可以使用数据修改CTE因为PostgreSQL的9.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;
Run Code Online (Sandbox Code Playgroud)
我借鉴价值foo,将其插入bar,让他们一起返回自动生成bar_id并插入该成foo.您也可以使用任何其他数据.
这是一个在sqlfiddle上玩的工作演示.
在澄清之前提供基本信息的原始答案.
基本形式是:
INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...
Run Code Online (Sandbox Code Playgroud)
不需要括号.你可以对任何表做同样的事情
INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...
Run Code Online (Sandbox Code Playgroud)
您可以加入到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
Run Code Online (Sandbox Code Playgroud)
它只是一个SELECT,就像其他任何一样 - 可以包括你插入的表.首先读取行,然后插入.
| 归档时间: |
|
| 查看次数: |
75750 次 |
| 最近记录: |