存储过程中不寻常的 UPDATE 语法
Unusual UPDATE syntax in stored procedure
我需要帮助来理解我在正在审计的遗留系统中发现的这个存储过程。特别是我无法理解 IF 条件中的 UPDATE 命令:UPDATE authors.author_id ...
.
DECLARE
p_mem_id ALIAS FOR ;
p_auth_id ALIAS FOR ;
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 版本中似乎是不受支持的语法[1](没有 SET,直接赋值),并且因为在我的数据库(pg_proc 中也没有)。
my_database=# \d authors.author_id;
Did not find any relation named "authors.author_id".
这是无效的 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
正如其他人所指出的,这是无效的语法。
但是,当您创建一个函数时,实际的函数代码("body")作为字符串传递并且不会被检查基本 create function
语法的部分解析。该字符串被移交给指定的 "language" 以进行进一步验证。
配置选项 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;
我想您在该数据库中看到的函数代码就是这样创建的。
一个有效的用例是创建相互依赖的函数,而不必考虑它们的创建顺序。
我需要帮助来理解我在正在审计的遗留系统中发现的这个存储过程。特别是我无法理解 IF 条件中的 UPDATE 命令:UPDATE authors.author_id ...
.
DECLARE
p_mem_id ALIAS FOR ;
p_auth_id ALIAS FOR ;
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 版本中似乎是不受支持的语法[1](没有 SET,直接赋值),并且因为在我的数据库(pg_proc 中也没有)。
my_database=# \d authors.author_id;
Did not find any relation named "authors.author_id".
这是无效的 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
正如其他人所指出的,这是无效的语法。
但是,当您创建一个函数时,实际的函数代码("body")作为字符串传递并且不会被检查基本 create function
语法的部分解析。该字符串被移交给指定的 "language" 以进行进一步验证。
配置选项 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;
我想您在该数据库中看到的函数代码就是这样创建的。
一个有效的用例是创建相互依赖的函数,而不必考虑它们的创建顺序。