在本节中,我们遵循 Tcl 的惯例,使用问号而不是方括号来指示语法概要中的可选元素。以下命令可用于从 PL/Tcl 函数体访问数据库
spi_exec
?-count n
? ?-array name
? command
?loop-body
?
执行以字符串形式给出的 SQL 命令。命令中的错误会导致引发错误。否则,spi_exec
的返回值是被命令处理的行数(选择、插入、更新或删除),如果命令是实用程序语句,则返回零。此外,如果命令是 SELECT
语句,则所选列的值将被放置在 Tcl 变量中,如下所述。
可选的 -count
值告诉 spi_exec
在检索到 n
行后停止,就像查询包含 LIMIT
子句一样。如果 n
为零,则查询将运行至完成,与省略 -count
相同。
如果命令是 SELECT
语句,则结果列的值将被放置到以列命名的 Tcl 变量中。如果给出 -array
选项,则列值将被存储到命名关联数组的元素中,使用列名作为数组索引。此外,结果中的当前行号(从零开始计数)将被存储到名为 “.tupno
” 的数组元素中,除非该名称用作结果中的列名。
如果命令是 SELECT
语句并且没有给出 loop-body
脚本,则只将结果的第一行存储到 Tcl 变量或数组元素中;任何剩余的行(如果有)将被忽略。如果查询未返回任何行,则不会进行任何存储。(可以通过检查 spi_exec
的结果来检测这种情况。)例如
spi_exec "SELECT count(*) AS cnt FROM pg_proc"
将 Tcl 变量 $cnt
设置为 pg_proc
系统目录中的行数。
如果给出了可选的 loop-body
参数,它将是 Tcl 脚本的一部分,该脚本将对查询结果中的每一行执行一次。(如果给定命令不是 SELECT
,则 loop-body
将被忽略。)每次迭代之前,当前行的列值将被存储到 Tcl 变量或数组元素中。例如
spi_exec -array C "SELECT * FROM pg_class" { elog DEBUG "have table $C(relname)" }
将为 pg_class
的每一行打印一条日志消息。此功能类似于其他 Tcl 循环构造;特别是 continue
和 break
在循环体中以通常的方式工作。
如果查询结果的一列为 NULL,则其目标变量将被 “unset”,而不是被设置。
spi_prepare
query
typelist
准备并保存查询计划以供以后执行。保存的计划将保留在本会话的整个生命周期中。
查询可以使用参数,即在实际执行计划时要提供的值的占位符。在查询字符串中,使用符号 $1
... $
来引用参数。如果查询使用参数,则必须以 Tcl 列表的形式给出参数类型的名称。(如果未使用参数,则为 n
typelist
写入空列表。)
spi_prepare
的返回值是一个查询 ID,将在后续调用 spi_execp
时使用。有关示例,请参阅 spi_execp
。
spi_execp
?-count n
? ?-array name
? ?-nulls string
? queryid
?value-list
? ?loop-body
?
执行先前使用 spi_prepare
准备的查询。 queryid
是 spi_prepare
返回的 ID。如果查询引用了参数,则必须提供 value-list
。这是一个 Tcl 列表,用于提供参数的实际值。该列表的长度必须与先前传递给 spi_prepare
的参数类型列表相同。如果查询没有参数,则省略 value-list
。
-nulls
的可选值是一个空格和 'n'
字符的字符串,告诉 spi_execp
哪些参数是 NULL 值。如果给出,它的长度必须与 value-list
严格相同。如果未给出,则所有参数值均为非空。
除了指定查询及其参数的方式不同之外,spi_execp
的工作方式与 spi_exec
完全相同。-count
、-array
和 loop-body
选项相同,结果值也相同。
以下是用准备好的计划的 PL/Tcl 函数示例
CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS $$ if {![ info exists GD(plan) ]} { # prepare the saved plan on the first call set GD(plan) [ spi_prepare \ "SELECT count(*) AS cnt FROM t1 WHERE num >= \$1 AND num <= \$2" \ [ list int4 int4 ] ] } spi_execp -count 1 $GD(plan) [ list $1 $2 ] return $cnt $$ LANGUAGE pltcl;
我们需要在传递给 spi_prepare
的查询字符串内部使用反斜杠,以确保 $
标记将按原样传递给 n
spi_prepare
,而不会被 Tcl 变量替换所替换。
subtransaction
command
包含在 command
中的 Tcl 脚本将在 SQL 子事务中执行。如果脚本返回错误,则在返回错误到周围的 Tcl 代码之前,将回滚整个子事务。有关详细信息和示例,请参阅 第 42.9 节。
quote
string
将给定字符串中出现的单引号和反斜杠字符都加倍。这可用于安全地引用要插入到传递给 spi_exec
或 spi_prepare
的 SQL 命令中的字符串。例如,考虑一下这样的 SQL 命令字符串
"SELECT '$val' AS ret"
其中 Tcl 变量 val
实际上包含 doesn't
。这将导致最终的命令字符串为
SELECT 'doesn't' AS ret
这将在 spi_exec
或 spi_prepare
期间导致解析错误。要正常工作,提交的命令应包含
SELECT 'doesn''t' AS ret
这可以使用 PL/Tcl 中的以下代码来形成
"SELECT '[ quote $val ]' AS ret"
spi_execp
的一个优点是,你不必像这样引用参数值,因为参数永远不会作为 SQL 命令字符串的一部分进行解析。
elog
level
msg
发出日志或错误消息。可能的级别为 DEBUG
、LOG
、INFO
、NOTICE
、WARNING
、ERROR
和 FATAL
。ERROR
会引发错误条件;如果周围的 Tcl 代码没有捕获到此错误,则错误会传播到调用查询,导致当前事务或子事务中止。这实际上与 Tcl 的 error
命令相同。FATAL
会中止事务并导致当前会话关闭。(可能没有充分的理由在 PL/Tcl 函数中使用此错误级别,但为了完整性,它被提供。)其他级别只生成不同优先级的消息。是否将特定优先级的消息报告给客户端、写入服务器日志或同时进行这两项操作,由 log_min_messages 和 client_min_messages 配置变量控制。有关更多信息,请参阅 第 19 章 和 第 42.8 节。
如果您在文档中发现任何错误,与您对特定功能的体验不符,或者需要进一步说明,请使用 此表格 报告文档问题。