PostgreSQL文件说:
SQL函数的整个主体在执行任何函数之前都会被解析。 虽然SQL函数可以包含 更改系统目录的命令 (例如CREATE TABLE),但是在对函数中的后续命令进行语法分析时,这些命令的效果将不可见。因此,例如, CREATE TABLE foo (...); INSERT INTO foo VALUES(...); 如果打包到单个SQL函数中将无法按预期工作 ,因为INSERT解析命令时foo尚不存在。 在这种情况下,建议使用PL / pgSQL代替SQL函数。
SQL函数的整个主体在执行任何函数之前都会被解析。 虽然SQL函数可以包含 更改系统目录的命令 (例如CREATE TABLE),但是在对函数中的后续命令进行语法分析时,这些命令的效果将不可见。因此,例如, CREATE TABLE foo (...); INSERT INTO foo VALUES(...); 如果打包到单个SQL函数中将无法按预期工作 ,因为INSERT解析命令时foo尚不存在。
CREATE TABLE
CREATE TABLE foo (...); INSERT INTO foo VALUES(...);
INSERT
在这种情况下,建议使用PL / pgSQL代替SQL函数。
为什么“在这种情况下,建议使用PL / pgSQL代替SQL函数”,而PL / pgSQL或SQL函数包含更改系统目录的命令,例如CREATE TABLE foo (...); INSERT INTO foo VALUES(...);?
“ SQL函数的整个主体在执行任何函数之前都会被解析”。PL / pgSQL函数不是真的吗?在解析和执行其主体中的命令方面,SQL函数和PL / pgSQL函数之间有什么区别?
您自己将手册中的关键句子加粗了:
SQL函数的整个主体在执行任何函数之前都会被解析。
另请参阅手册中有关 解析器阶段 的信息。
它由两个主要部分组成: 解析器 和 转换过程 。引用手册:
在 改造过程中 需要由解析器树递回作为输入,并确实了解哪些表,函数,和运营商查询所引用所需的语义解释。
如果SQL函数包含以下命令:
几乎同时计划了这两个语句(基于系统目录的相同快照)。因此,INSERT不能看到表“ foo”可能是由上一条CREATE命令创建的。这就产生 了以下问题之一 :
CREATE
search_patch
ERROR: relation "foo" does not exist
使用 PL / pgSQL 函数不会发生这种情况,因为它会将SQL命令像预处理语句一样按 _ 顺序_ 计划和执行。因此,每个语句都可以查看在先前语句中创建的对象。
因此,从未访问过的语句甚至都不会被计划-与SQL函数不同。语句的执行计划可以缓存在同一会话中-与SQL函数不同。在此处阅读有关PL / pgSQL函数中计划缓存的详细信息。