存储过程中异常的UPDATE语法

时间:2019-01-16 22:24:01

标签: sql postgresql sql-update postgresql-9.3

我需要帮助来了解我在审核的旧系统中发现的此存储过程。特别是,我无法理解IF条件UPDATE authors.author_id ...中的UPDATE命令。

DECLARE

    p_mem_id ALIAS FOR $1;
    p_auth_id ALIAS FOR $2;

    res     bool ;
    v_rec   authors.author_gov_id%ROWTYPE;

    BEGIN
        res := 0;
        SELECT INTO v_rec * FROM authors.author_gov_id WHERE author_id = p_auth_id;

        IF FOUND THEN
              UPDATE authors.author_id = (SELECT gov_id FROM authors.gov_id WHERE mem_id=p_mem_id);
        ELSE
              .. snip ..
        END IF;

        RETURN res;
    END;

我发现这很令人困惑,因为在我的PSQL版本(无SET和直接赋值)中,此更新语句似乎不受语法支持[1],并且在数据库中没有称为authors.author_id的关系(pg_proc中也没有)。

my_database=# \d authors.author_id;
Did not find any relation named "authors.author_id".

[1] https://www.postgresql.org/docs/9.3/sql-update.html

2 个答案:

答案 0 :(得分:1)

正如其他人指出的那样,这是无效的语法。

但是,当您创建函数时,实际的函数代码(“主体”)将作为字符串传递,并且不会由检查基本create function语法的部分进行解析。该字符串将移交给指定的“语言”以进行进一步验证。

配置选项check_function_bodies控制在创建函数时是否完成此检查。

如果将其设置为off,则正文无效,并且create function()成功,即使正文无效。

因此,以下代码成功创建了函数:

set check_function_bodies=off;

create function invalid()
  returns void
as
$$
begin
  update foo.bar = 'this is so wrong';
end;
$$
language plpgsql;

我猜您在该数据库中看到的功能代码就是用这种方式创建的。


一个有效的用例是创建相互依赖的函数,而不必考虑创建它们的顺序。

答案 1 :(得分:0)

这是无效的SQL语法,当您实际调用此函数时,postgres会阻塞。

在看到注释表明我不感到困惑后,我发现了一个已安装此存储过程的登台数据库,并试图引起UPDATE子句触发-导致以下错误:

ERROR:  syntax error at or near "="
LINE 1: UPDATE authors.author_id = (SELECT gov_id FROM authors...
                                ^
QUERY:  UPDATE authors.author_id = (SELECT gov_id FROM authors.gov_id WHERE mem_id=p_mem_id)
CONTEXT:  PL/pgSQL function authors.copy_govid(integer,integer) line 15 at SQL statement