【发布时间】:2015-03-13 22:46:10
【问题描述】:
我的问题是对 Erwin Brandstetter 在this thread 中关于正确使用WITH 的出色回答的某种扩展。
我的旧查询如下所示:
WITH x AS (
INSERT INTO d (dm_id)
SELECT dm_id
FROM dm, import i
WHERE dm.dm_name = i.dm_name
RETURNING d_id
), y AS (
INSERT INTO z (d_id)
SELECT d_id
FROM x
RETURNING z_id
)
INSERT INTO port (z_id)
SELECT z_id
FROM y;
这就像一个魅力。但是现在,已经添加了另一个表 (r)(与表 d 的结构相同),并且有可能必须将 d_id 或 r_id 添加到表 z。这取决于dm_name 或rm_name 在表import 中是否为空。所以我的理论方法是这样的:
SELECT dm_name, rm_name
,CASE WHEN dm_name != '' THEN
WITH x AS (
INSERT INTO d (dm_id)
SELECT dm_id
FROM dm, import i
WHERE dm.dm_name = i.dm_name
RETURNING d_id
), y AS (
INSERT INTO z (d_id)
SELECT d_id
FROM x
RETURNING z_id
)
INSERT INTO port (z_id)
SELECT z_id
FROM y
END
,CASE WHEN rm_name != '' THEN
WITH x AS (
INSERT INTO r (rm_id)
SELECT rm_id
FROM rm, import i
WHERE rm.rm_name = i.rm_name
RETURNING r_id
), y AS (
INSERT INTO z (r_id)
SELECT r_id
FROM x
RETURNING z_id
)
INSERT INTO port (z_id)
SELECT z_id
FROM y
END
FROM import;
但 PostgreSQL 告诉我:
“INSERT INTO 端口 (z_id)”处或附近的语法错误
虽然查询的那部分应该是正确的,因为它已经工作了。
我希望你能帮我解决这个问题。 :)
为了更好地理解 - 这是表结构:
CREATE TABLE import (
dm_name character varying,
rm_name character varying
-- many other columns which are not relevant
);
CREATE TABLE dm (
dm_id integer NOT NULL, -- serial
dm_name character varying
-- plus more columns
);
CREATE TABLE d (
d_id integer NOT NULL, -- serial
dm_id integer -- references dm.dm_id
-- plus more columns
);
CREATE TABLE rm (
rm_id integer NOT NULL, -- serial
rm_name character varying
-- plus more columns
);
CREATE TABLE r (
r_id integer NOT NULL, -- serial
rm_id integer -- references rm.rm_id
-- plus more columns
);
CREATE TABLE z (
z_id integer NOT NULL, -- serial
r_id integer, -- references r.r_id
d_id integer -- references d.d_id
-- plus more columns
);
CREATE TABLE port (
p_id integer NOT NULL, -- serial
z_id integer, -- references z.z_id
-- plus more columns
);
导入表不知道 id,因为它们是在原子化过程中生成的。 dm 和 rm 表用于已从导入表中提取的设备模型。 d 和 r 表适用于实际设备。由于端口只能有 r-device 或 d-device 或没有,因此引入 z-table 以在 port-table 中只有一个字段表示所有可能性。 d/r 和 dm/rm 表不能组合,因为它们有不同的特殊列,具体取决于设备类型。
【问题讨论】:
-
@Lamak,它在 postgresql 9.2+ 中有效,但我希望大多数人不要这样使用它。对我来说,CTE 能够在事务中分离、简化和重用复杂的逻辑。将插入物放在那里只会否定受益
-
@HaleemurAli:这实际上是一个非常好的功能。在单个语句中删除、插入和显示已删除的行:sqlfiddle.com/#!15/7b0ea/2
-
您的查询中缺少表别名:
FROM dm, importi。还有一些;不应该在那里。但还有更多。我会添加一个答案。 -
感谢 Erwin,但这些错误仅在此编辑版本中出现。真正的查询已经修复了它们(只是忘记在这里更正)。但我仍然收到语法错误(phppgadmin 指向 INSERT):-(
标签: sql postgresql case common-table-expression sql-insert