PostgreSQL如何从匿名代码块返回数据?

Nar*_*yck 6 postgresql query

我有一个表 mytable (id, "someLongURI", status, "userId") 和一个工作查询:

UPDATE          mytable
SET             status = 'IN_WORK'
WHERE           "someLongURI" IN (
    SELECT      "someLongURI"
    FROM        mytable
    WHERE       status = 'UNUSED'
    AND         pg_try_advisory_xact_lock(id)
    ORDER BY    id ASC 
    LIMIT       1
    FOR UPDATE 
)
RETURNING       id, "someLongURI";
Run Code Online (Sandbox Code Playgroud)

但现在我需要检查“userId”参数,并基于此选择现有行或更新(并接收更新的行)。类似的东西(在 MySQL 中这可以工作):

IF NOT EXISTS (
    SELECT          1
    FROM            mytable tbl
    WHERE           tbl."userId" = 123
)
THEN
    UPDATE          mytable tbl
    SET             tbl.status = 'IN_WORK',
                    tbl."userId" = 123
    WHERE           tbl."someLongURI" IN (
        SELECT      "someLongURI"
        FROM        tbl.mytable
        WHERE       tbl.status = 'UNUSED'
            AND     pg_try_advisory_xact_lock(id)
        ORDER BY    id ASC 
        LIMIT       1
        FOR UPDATE 
    )
    RETURNING   tbl.id, tbl."someLongURI";
ELSE
    SELECT          tbl.id, tbl."someLongURI"
    FROM            mytable tbl
    WHERE           tbl."userId" = 123;
END IF;
Run Code Online (Sandbox Code Playgroud)

我用DO $$ BEGIN {...} END $$;包装它 但这对我不起作用。我最后想到的一件事是:

DO
    RETURNS TABLE (id INT4, "someLongURI" TEXT) AS
$$
DECLARE
    "_userId" INT4;
BEGIN
    "_userId" = 123;

    IF NOT EXISTS (
        SELECT          1
        FROM            mytable tbl
        WHERE           tbl."userId" = "_userId"
    )
    THEN
        UPDATE          mytable tbl
        SET             tbl.status = 'IN_WORK'
                        tbl."userId" = "_userId"
        WHERE           tbl."someLongURI" IN (
            SELECT      "someLongURI"
            FROM        tbl.mytable
            WHERE       tbl.status = 'UNUSED'
                AND     pg_try_advisory_xact_lock(id)
            ORDER BY    id ASC 
            LIMIT       1
            FOR UPDATE 
        )
        RETURNING       tbl.id, tbl."someLongURI";
    ELSE
        SELECT          tbl.id, tbl."someLongURI"
        FROM            mytable tbl
        WHERE           tbl."userId" = "_userId";
    END IF;
END $$;
Run Code Online (Sandbox Code Playgroud)

无法理解我需要在这个匿名代码块中添加“RETURNS”或其他一些语句来接收查询结果

小智 5

使用 Postgres,您可以在单个数据修改 CTE中完成此操作,而不需要 IF 语句:

WITH data AS (
    SELECT          tbl.id, tbl."someLongURI"
    FROM            mytable tbl
    WHERE           tbl."userId" = 123;
), changed AS (
    UPDATE          mytable tbl
    SET             tbl.status = 'IN_WORK',
                    tbl."userId" = 123
    WHERE           tbl."someLongURI" IN (
        SELECT      "someLongURI"
        FROM        tbl.mytable
        WHERE       tbl.status = 'UNUSED'
            AND     pg_try_advisory_xact_lock(id)
        ORDER BY    id ASC 
        LIMIT       1
        FOR UPDATE 
    )
    AND NOT EXISTS (SELECT * FROM data)
    RETURNING   tbl.id, tbl."someLongURI"
)
SELECT *
FROM changed
UNION ALL
SELECT *
FROM data
WHERE NOT EXISTS (SELECT * FROM changed);
Run Code Online (Sandbox Code Playgroud)