选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.0 已于 2015 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

40.5. 从 PL/Tcl 访问数据库 #

在 PL/Tcl 函数体中可以使用下列命令来访问数据库:

spi_exec ?-count n? ?-array name? command ?loop-body?

执行以字符串形式给出的 SQL 命令。命令出错时会引发错误。 否则,spi_exec 的返回值是该命令处理的 行数(选出、插入、更新或删除的行),如果命令是工具语句则 返回零。此外,如果命令是 SELECT 语句,则所选列 的值会按下文所述放入 Tcl 变量中。

可选的 -count 值告诉 spi_exec 此命令最多处理多少行,其效果类似 于将查询设为游标后执行 FETCH n

如果命令是 SELECT 语句,则结果列的值会放入以列名 命名的 Tcl 变量中。如果给定了 -array 选项,则列值 会存储在指定的关联数组元素中,列名用作数组索引。

如果命令是 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 循环构造;特别是 continuebreak 在 循环体中按通常方式工作。

如果查询结果的某一列为空值,则其目标变量会被 unset(取消设置),而不是被设置。

spi_prepare query typelist

准备并保存一个查询计划以供后续执行。保存的计划会在当前会话 的整个生命周期内保留。

查询可以使用参数,也就是在实际执行该计划时要提供的值的占位 符。在查询字符串中,用符号 $1 ... $n 引用参数。如果查询使用了参数,则必须以 Tcl 列表的形式给出 各参数类型的名称。(如果未使用参数,则为 typelist 写一个空列表。)

spi_prepare 的返回值是一个查询 ID,供 后续调用 spi_execp 时使用。示例参见 spi_execp

spi_execp ?-count n? ?-array name? ?-nulls string? queryid ?value-list? ?loop-body?

执行先前用 spi_prepare 准备好的查询。 queryidspi_prepare 返回的 ID。如果查询引用了参数,则 必须提供 value-list。这是参数实际 值构成的 Tcl 列表。该列表的长度必须与先前提供给 spi_prepare 的参数类型列表相同。如果查询没有 参数,则省略 value-list

可选的 -nulls 值是由空格和 'n' 字符组成的字符串,用来告诉 spi_execp 哪些参数是空值。如果给出, 它的长度必须与 value-list 完全 相同。如果未给出,则所有参数值都视为非空值。

除了指定查询及其参数的方式之外, spi_execp 的工作方式与 spi_exec 完全相同。-count-arrayloop-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 执行变量替换。

spi_lastoid

如果最后一次 spi_execspi_execp 执行的是单行 INSERT,且 被修改的表包含 OID,则返回所插入行的 OID。(否则返回零。)

quote string

将给定字符串中的所有单引号和反斜杠字符都加倍。这可用于安全 地为那些要插入到传给 spi_execspi_prepare 的 SQL 命令中的字符串加 引号。例如,考虑如下 SQL 命令字符串:

"SELECT '$val' AS ret"

其中 Tcl 变量 val 的实际内容是 doesn't。这会得到最终命令字符串:

SELECT 'doesn't' AS ret

这会在 spi_execspi_prepare 期间导致解析错误。要使其 正常工作,提交的命令应当包含:

SELECT 'doesn''t' AS ret

它在 PL/Tcl 中可以这样构成:

"SELECT '[ quote $val ]' AS ret"

spi_execp 的一个优点是,你不必像这样为 参数值加引号,因为参数永远不会被当作 SQL 命令字符串的一部分 来解析。

elog level msg

发出日志或错误消息。可用级别包括 DEBUGLOGINFONOTICEWARNINGERRORFATALERROR 会引发错误条件;如果外围 Tcl 代码没有捕获它,该错误就会 传播到调用查询,导致当前事务或子事务中止。这实际上与 Tcl 的 error 命令相同。 FATAL 会中止事务并导致当前会话关闭。 (在 PL/Tcl 函数中使用这个错误级别可能并没有什么充分理由, 但为了完整性仍提供它。)其他级别只会生成不同优先级的消息。 某个特定优先级的消息是报告给客户端、写入服务器日志,还是 两者都做,由 log_min_messagesclient_min_messages 配置变量控制。 参见 第 18 章 了解更多信息。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。