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

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.1 已于 2016 年 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 在 循环体中按通常方式工作。

如果查询结果的某一列为空值,对应的目标变量将被取消设置而不是被设置。

spi_prepare query typelist

为以后的执行准备并保存一个查询计划。保存的计划将在当前会话的生存期内保留。

查询可以使用参数,也就是在计划实际执行时才提供值的占位符。在查询字符串中,用符号 $1 ... $n 引用参数。 If the query uses parameters, the names of the parameter types must be given as a Tcl list. (Write an empty list for typelist if no parameters are used.)

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 完全相同。 If it is not given, all the parameter values are nonnull.

除了指定查询及其参数的方式之外,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;

We need backslashes inside the query string given to spi_prepare to ensure that the $n markers will be passed through to spi_prepare as-is, and not replaced by Tcl variable substitution.

spi_lastoid

返回最近一次 spi_execspi_execp 插入的行的 OID,前提是该命令是单行 INSERT 且被修改的表包含 OID。(否则返回零。)

quote string

把给定字符串中所有单引号和反斜线字符加倍。这可以用来安全地引用将被插入到交给 spi_execspi_prepare 的 SQL 命令中的字符串。例如,考虑下面这样的 SQL 命令字符串:

"SELECT '$val' AS ret"

where the Tcl variable val actually contains doesn't. This would result in the final command string:

SELECT 'doesn't' AS ret

which would cause a parse error during spi_exec or spi_prepare. To work properly, the submitted command should contain:

SELECT 'doesn''t' AS ret

which can be formed in PL/Tcl using:

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

One advantage of spi_execp is that you don't have to quote parameter values like this, since the parameters are never parsed as part of an SQL command string.

elog level msg

发出一条日志或错误消息。可用的级别有 DEBUGLOGINFONOTICEWARNINGERRORFATALERROR 会引发一个错误条件;如果周围的 Tcl 代码没有捕获它,该错误会传播到调用查询,导致当前事务或子事务被中止。 This is effectively the same as the Tcl error command. FATAL aborts the transaction and causes the current session to shut down. (There is probably no good reason to use this error level in PL/Tcl functions, but it's provided for completeness.) The other levels only generate messages of different priority levels. Whether messages of a particular priority are reported to the client, written to the server log, or both is controlled by the log_min_messages and client_min_messages configuration variables. See 第 18 章 for more information.

提交更正

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