不能 select 来自临时 table
Can't select from a temporary table
我有 3 个 tables - T_USER
,T_PRIVILEGE
和 T_USER_PRIVILEGES
.
T_USER_PRIVILEGES
是一个引用 table,包含从 T_USER
行到 T_PRIVILEGE
行的引用。我想从 T_USER
中删除一行,为此我需要先删除 T_USER_PRIVILEGES
中的引用,以及 T_PRIVILEGE
.
中的所有引用行
我想创建一个临时 table 来保存 T_PRIVILEGE
中的所有引用行,然后删除 T_USER_PRIVILEGES
中的所有引用,最后删除 [=16] 中的所有行=] 存储在临时 table.
我尝试做的是创建一个存储过程来完成它:
CREATE FUNCTION "SP_DELETE_USER"(userid character varying) RETURNS void AS
$BODY$CREATE TEMP TABLE temp_privilege_ids
(
privilege_id VARCHAR(100)
);
SELECT "PRIVILEGE_ID"
INTO temp_privilege_ids
FROM
(SELECT * FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = userid) as foo;
DELETE FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = userid;
DELETE FROM "T_PRIVILEGE"
WHERE "ID" IN
(SELECT privilege_id FROM temp_privilege_ids);$BODY$
LANGUAGE sql VOLATILE NOT LEAKPROOF;
ALTER FUNCTION public."SP_DELETE_USER"(character varying)
OWNER TO postgres;
userid
是 SP 的参数。
当我尝试创建 SP pgAdmin 时说:
relation "temp_privilege_ids" does not exist
LINE 19: (SELECT privilege_id FROM temp_privilege_ids);$BODY$
我到处寻找解释,但没有找到答案。
有人有想法吗?
这是参考table:
CREATE TABLE "T_USER_PRIVILEGES" (
"USER_ID" character varying(100) NOT NULL,
"PRIVILEGE_ID" character varying(100) NOT NULL,
CONSTRAINT "PK_T_USER_PRIVILEGES" PRIMARY KEY ("USER_ID", "PRIVILEGE_ID"),
CONSTRAINT "FK_T_USER_PRIVILEGES_PRIVILEGES" FOREIGN KEY ("PRIVILEGE_ID")
REFERENCES "T_PRIVILEGE" ("ID") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT "FK_T_USER_PRIVILEGES_USER" FOREIGN KEY ("USER_ID")
REFERENCES "T_USER" ("ID") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
CREATE INDEX "FKI_T_USER_PRIVILEGES_PRIVILEGES"
ON "T_USER_PRIVILEGES" ("PRIVILEGE_ID" COLLATE pg_catalog."default");
语言 SQL 功能已计划一次,因此您不能引用任何尚不存在的 table。您可以手动创建 temp table 以在创建时通过表面语法检查并允许创建函数,但该函数在执行时仍然会失败。
您可以使用 plpgsql 函数实现您正在尝试的功能(应用评论中已提供的一些建议@a_horse_with_no_name):
CREATE OR REPLACE FUNCTION "SP_DELETE_USER"(_userid varchar) RETURNS void AS
$func$
BEGIN
CREATE TEMP TABLE temp_privilege_ids ON COMMIT DROP AS
SELECT "PRIVILEGE_ID"
FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = _userid;
DELETE FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = _userid;
DELETE FROM "T_PRIVILEGE" t
USING temp_privilege_ids tmp
WHERE t."ID" = tmp."PRIVILEGE_ID";
END
$func$ LANGUAGE plpgsql;
但这仍然是不必要的复杂。只需使用 data-modifying CTE:
WITH del1 AS (
DELETE FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = _userid -- provide userid here
RETURNING "PRIVILEGE_ID"
)
DELETE FROM "T_PRIVILEGE" t
USING del1
WHERE t."ID" = del1."PRIVILEGE_ID";
抛开我对您的数据库设计和命名约定的疑虑。
,你的 FK 约束 "FK_T_USER_PRIVILEGES_PRIVILEGES"
似乎指向了 错误的方向 :它适用于多个用户可以链接到相同的特权(这是有道理的)。
如果是这样,请删除此约束并改为在 "T_PRIVILEGE"."ID"
上创建一个约束:
ALTER TABLE "T_PRIVILEGE"
ADD CONSTRAINT "FK_T_PRIVILEGE_ID" FOREIGN KEY ("ID")
REFERENCES "T_USER_PRIVILEGES"("PRIVILEGE_ID")
ON UPDATE CASCADE ON DELETE CASCADE;
当您删除 "T_USER_PRIVILEGES"
中的行时,由于 CASCADE
子句,权限会 自动删除 。
仍然是一个奇怪的设计。 "Privileges" 通常是多个用户可以共享的内容...
我有 3 个 tables - T_USER
,T_PRIVILEGE
和 T_USER_PRIVILEGES
.
T_USER_PRIVILEGES
是一个引用 table,包含从 T_USER
行到 T_PRIVILEGE
行的引用。我想从 T_USER
中删除一行,为此我需要先删除 T_USER_PRIVILEGES
中的引用,以及 T_PRIVILEGE
.
我想创建一个临时 table 来保存 T_PRIVILEGE
中的所有引用行,然后删除 T_USER_PRIVILEGES
中的所有引用,最后删除 [=16] 中的所有行=] 存储在临时 table.
我尝试做的是创建一个存储过程来完成它:
CREATE FUNCTION "SP_DELETE_USER"(userid character varying) RETURNS void AS
$BODY$CREATE TEMP TABLE temp_privilege_ids
(
privilege_id VARCHAR(100)
);
SELECT "PRIVILEGE_ID"
INTO temp_privilege_ids
FROM
(SELECT * FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = userid) as foo;
DELETE FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = userid;
DELETE FROM "T_PRIVILEGE"
WHERE "ID" IN
(SELECT privilege_id FROM temp_privilege_ids);$BODY$
LANGUAGE sql VOLATILE NOT LEAKPROOF;
ALTER FUNCTION public."SP_DELETE_USER"(character varying)
OWNER TO postgres;
userid
是 SP 的参数。
当我尝试创建 SP pgAdmin 时说:
relation "temp_privilege_ids" does not exist LINE 19: (SELECT privilege_id FROM temp_privilege_ids);$BODY$
我到处寻找解释,但没有找到答案。 有人有想法吗?
这是参考table:
CREATE TABLE "T_USER_PRIVILEGES" (
"USER_ID" character varying(100) NOT NULL,
"PRIVILEGE_ID" character varying(100) NOT NULL,
CONSTRAINT "PK_T_USER_PRIVILEGES" PRIMARY KEY ("USER_ID", "PRIVILEGE_ID"),
CONSTRAINT "FK_T_USER_PRIVILEGES_PRIVILEGES" FOREIGN KEY ("PRIVILEGE_ID")
REFERENCES "T_PRIVILEGE" ("ID") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT "FK_T_USER_PRIVILEGES_USER" FOREIGN KEY ("USER_ID")
REFERENCES "T_USER" ("ID") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
CREATE INDEX "FKI_T_USER_PRIVILEGES_PRIVILEGES"
ON "T_USER_PRIVILEGES" ("PRIVILEGE_ID" COLLATE pg_catalog."default");
语言 SQL 功能已计划一次,因此您不能引用任何尚不存在的 table。您可以手动创建 temp table 以在创建时通过表面语法检查并允许创建函数,但该函数在执行时仍然会失败。
您可以使用 plpgsql 函数实现您正在尝试的功能(应用评论中已提供的一些建议@a_horse_with_no_name):
CREATE OR REPLACE FUNCTION "SP_DELETE_USER"(_userid varchar) RETURNS void AS
$func$
BEGIN
CREATE TEMP TABLE temp_privilege_ids ON COMMIT DROP AS
SELECT "PRIVILEGE_ID"
FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = _userid;
DELETE FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = _userid;
DELETE FROM "T_PRIVILEGE" t
USING temp_privilege_ids tmp
WHERE t."ID" = tmp."PRIVILEGE_ID";
END
$func$ LANGUAGE plpgsql;
但这仍然是不必要的复杂。只需使用 data-modifying CTE:
WITH del1 AS (
DELETE FROM "T_USER_PRIVILEGES"
WHERE "USER_ID" = _userid -- provide userid here
RETURNING "PRIVILEGE_ID"
)
DELETE FROM "T_PRIVILEGE" t
USING del1
WHERE t."ID" = del1."PRIVILEGE_ID";
抛开我对您的数据库设计和命名约定的疑虑。
"FK_T_USER_PRIVILEGES_PRIVILEGES"
似乎指向了 错误的方向 :它适用于多个用户可以链接到相同的特权(这是有道理的)。
如果是这样,请删除此约束并改为在 "T_PRIVILEGE"."ID"
上创建一个约束:
ALTER TABLE "T_PRIVILEGE"
ADD CONSTRAINT "FK_T_PRIVILEGE_ID" FOREIGN KEY ("ID")
REFERENCES "T_USER_PRIVILEGES"("PRIVILEGE_ID")
ON UPDATE CASCADE ON DELETE CASCADE;
当您删除 "T_USER_PRIVILEGES"
中的行时,由于 CASCADE
子句,权限会 自动删除 。
仍然是一个奇怪的设计。 "Privileges" 通常是多个用户可以共享的内容...