繁体   English   中英

在PGSQL查询中重用变量

[英]Reusing variables in PGSQL queries

我有一个查询,将其简化为:

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查询中声明一次变量并重用它?

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

不幸的是,这不是一个方法。 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块不能接受参数或返回行集。 因此,这不是理想的方法,但是可以工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM