如何在不创建函数的情况下运行plpgsql?

arn*_*old 5 postgresql plpgsql

我想在Postgres中以编程方式运行SQL,而无需创建函数。

原因:确保我的plpgsql可以事先工作,并且在将查询提交给函数之前先对其进行“解释分析”。

我是Postgres的新手,我认为这很简单。我找不到任何示例。也许不可能吗?下面的代码如何工作?

DO
$body$
DECLARE
  v_name_short VARCHAR;
BEGIN

v_name_short := 'test Account 1';

     RETURN QUERY
        SELECT 
            a.name_short, 
            a.name_long
        FROM enterprise.account a 
        WHERE 
            CASE WHEN v_name_short IS NOT NULL THEN
               LOWER(a.name_short) = LOWER(v_name_short)
            ELSE
               1 = 1   
            END;
END;
$body$
LANGUAGE 'plpgsql';
Run Code Online (Sandbox Code Playgroud)

同样,这里的目标是测试我的SQL,就像在这种情况下,我想确保我的CASE语句仍在使用我创建的索引(LOWER(name_short))。无论如何,我收到此错误消息:

错误:无法在非SETOF函数中使用RETURN QUERY

我要问的在Postgres中可能吗?如果没有,是否可以查询函数内部的分析计划?

Clo*_*eto 8

匿名代码块do总是返回void

代码块被视为没有参数的函数体,返回 void

要在do块内执行查询,请使用perform

do $$
    begin
    perform * from t;
    end
$$;
Run Code Online (Sandbox Code Playgroud)

https://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-NORESULT


kli*_*lin 6

匿名代码块返回 void。但是,您可以使用临时表的技巧,例如

CREATE TEMP TABLE IF NOT EXISTS trace (name_short text, name_long text);

DO
$body$
DECLARE
    v_name_short VARCHAR;
BEGIN

    v_name_short := 'test Account 1';

    INSERT INTO trace 
        SELECT 
            a.name_short, 
            a.name_long
        FROM enterprise.account a 
        WHERE 
            CASE WHEN v_name_short IS NOT NULL THEN
               LOWER(a.name_short) = LOWER(v_name_short)
            ELSE
               1 = 1   
            END;
END;
$body$
LANGUAGE 'plpgsql'; 

SELECT * FROM trace;
-- DROP TABLE trace;
Run Code Online (Sandbox Code Playgroud)

随着EXPLAIN ANALYSE你就可以分析只有一个简单的SQL查询,而不是一个功能,做块,也不是一个脚本。所以你可以试试:

EXPLAIN ANALYSE
    SELECT 
        a.name_short, 
        a.name_long
    FROM enterprise.account a 
    WHERE 
        CASE WHEN 'test Account 1' IS NOT NULL THEN
           LOWER(a.name_short) = LOWER('test Account 1')
        ELSE
           1 = 1   
        END;
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,您不能使用变量,因为规划器无法识别它,请改用文字。


Erw*_*ter 5

在常规 PL/pgSQL 函数和语句之间还有第三个选项DO临时函数。它没有明确记录,但它只是使用标准的 Postgres 功能。

实际上,您可以使用附加模块auto-explain获取嵌套在 PL/pgSQL 代码块中的 SQL 语句的详细查询计划。看:

但是您必须使用CASE表达式中每个分支的值来测试您的函数,以确保涵盖所有内容。Postgres 仅对CREATE FUNCTION.

准备好的语句可能是另一种选择。PL/pgSQL 内部处理 SQL 语句的方式与准备语句非常相似: