我有一个查询,我已经简化了一点:
WITH users AS (
SELECT member_id FROM group_members AS gm
JOIN groups AS g on gm.group_id = g.id
WHERE g.id = 1337 OR g.parents @> ARRAY[1337]
)
UPDATE access SET revoked = TRUE
WHERE user_id IN (SELECT member_id FROM users)
RETURNING user_id;
这有效,但我必须多次输入id值(1337)。在我的抽象例子中,这并不是那么糟糕,但是对于我更复杂的现实世界查询而言却变得非常丑陋。因为我使用PHP / PDO,所以我必须多次传入相同的变量。
我正在寻找的是一次声明我的变量然后重复使用它的技巧,例如:
DECLARE gid = 1337
WITH users AS (
SELECT member_id FROM group_members AS gm
JOIN groups AS g on gm.group_id = g.id
WHERE g.id = gid OR g.parents @> ARRAY[gid]
)
UPDATE access SET revoked = TRUE
WHERE user_id IN (SELECT member_id FROM users)
RETURNING user_id;
但显然这不起作用。
有没有办法在pgsql查询中声明一次变量并重用它?
答案 0 :(得分:2)
with gid as (
select 1337 as gid
), users as (
select member_id
from
group_members as gm
join
groups as g on gm.group_id = g.id
where
g.id = (select gid from gid) or
g.parents @> array[(select gid from gid)]
)
update access
set revoked = true
where user_id in (select member_id from users)
如果子查询太丑,则进行交叉连接
with gid as (
select 1337 as gid
), users as (
select member_id
from
group_members as gm
join
groups as g on gm.group_id = g.id
cross join
gid
where g.id = gid or g.parents @> array[gid]
)
update access
set revoked = true
where user_id in (select member_id from users)
但是如果你从PHP传递参数,那么我没有看到只是将参数持有者放在1337
答案 1 :(得分:2)
不幸的是,没有良好的方式。 Clodaldo已经展示了在纯SQL中真正可行的唯一方法。
另一种方式,以及我通常所做的,是将它包装在一个简单的SQL函数中。
CREATE OR REPLACE FUNCTION do_whatever(gid integer) RETURNS SETOF integer AS $$
WITH users AS (
SELECT member_id FROM group_members AS gm
JOIN groups AS g on gm.group_id = g.id
WHERE g.id = $1 OR g.parents @> ARRAY[$1]
)
UPDATE access SET revoked = TRUE
WHERE user_id IN (SELECT member_id FROM users)
RETURNING user_id;
$$ LANGUAGE sql;
SELECT * FROM do_whatever(1337);
不幸的是,PostgreSQL没有TEMPORARY
个函数,而DO
块不能获取参数或返回行集。所以它不理想,但它有效。