【问题标题】:PostgreSQL: Access enclosing function's argument inside DO blockPostgreSQL:访问 DO 块内的封闭函数的参数
【发布时间】:2017-11-02 11:23:27
【问题描述】:

我有一个带有 DO 块的 SQL 函数,当尝试访问 DO 块内的封闭函数的参数时,我收到“列不存在”错误。我错过了什么?

CREATE OR REPLACE FUNCTION f1(a1 TEXT) RETURNS VOID AS $$
DO $DO$
BEGIN
    RAISE NOTICE 'a1 = %', a1;
END
$DO$;
$$ LANGUAGE SQL VOLATILE;

SELECT f1('AA');

错误:列“a1”不存在 SQL 状态:42703 上下文: PL/pgSQL 函数 inline_code_block 第 3 行在 RAISE SQL函数“f1”语句1

【问题讨论】:

  • 这没有意义。如果你想使用 PL/pgSQL,那你为什么不干脆把那个函数变成一个 PL/pgSQL 函数呢?
  • 我的实际函数已经包含一些重要的 SQL 代码,我宁愿不删除它并将其重新创建为 plpgsql。
  • 一个 SQL 函数只能包含一条 SQL 语句,因此将其转换为 PL/pgSQL 函数不需要太多工作。您只需添加一个begin ...end,在select 前面添加一个return query,然后将language sql 更改为语言plpgsql。您显然需要 PL/pgSQL,否则您将没有DO 块。
  • 原来的函数确实包含几个SQL语句。我知道只有最后一个可以返回值的事实。无论如何,我确实删除了该函数并创建为 PLPGSQL。

标签: postgresql stored-procedures scope plpgsql


【解决方案1】:

我猜您希望有可能在 SQL 函数中发出通知。但是 DO 块不是一个好主意,因为函数的参数在其中不可见。相反,您可以准备一个引发通知的辅助函数:

create or replace function raise_notice(anyelement)
returns void language plpgsql as $$
begin
    raise notice '%', $1;
end $$;

现在您可以在 SQL 函数中使用它,例如:

create or replace function f1(a1 text)
returns text language sql as $$
    select raise_notice(a1);
    select a1;
$$;

select f1('some text');

NOTICE:  some text
CONTEXT:  PL/pgSQL function raise_notice(anyelement) line 3 at RAISE
SQL function "f1" statement 1
    f1     
-----------
 some text
(1 row)

【讨论】:

  • 其实没有...我的初衷是尽可能的保留在纯SQL函数中,只把plpgsql放在DO块中,但是好像这种混合行不通,所以我'已将整个函数更改为 plpgsql。
【解决方案2】:

你有错误的语言规范

$$ LANGUAGE SQL VOLATILE;

应该是:

$$ LANGUAGE plpgsql VOLATILE;

DO语句是新的,默认有plpgsql语言。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多