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

在本节中,我们遵循通常的Tcl惯例,使用问号而不是括号来表示语法大纲中的可选元素。以下命令可用于从PL/Tcl函数体访问数据库:

``高级执行官?-数*n*? ?-阵列*名称*? *命令* ?*环体*?

执行以字符串形式给出的SQL命令。命令中的错误导致引发错误。否则高级执行官是命令处理(选择、插入、更新或删除)的行数,如果命令是实用程序语句,则为零。此外,如果命令是选择语句中,所选列的值放置在Tcl变量中,如下所述。

可选的-数价值告诉我们高级执行官命令中要处理的最大行数。其效果相当于将查询设置为游标,然后取回*n*.

如果命令是选择语句中,结果列的值被放入以列命名的Tcl变量中。如果-阵列选项,则列值存储到命名关联数组的元素中,列名称用作数组索引。此外,结果中的当前行号(从零开始计数)被存储到名为“”的数组元素中图普诺先生,除非该名称在结果中用作列名。

如果命令是选择声明和否*环体*脚本,然后只将第一行结果存储到Tcl变量或数组元素中;其余的行(如果有)将被忽略。如果查询不返回任何行,则不会进行存储。(通过检查检测结果,可以检测到这种情况。)高级执行官)例如:

spi_exec "SELECT count(*) AS cnt FROM pg_proc"

将设置Tcl变量$cnt到中的行数pg_程序系统目录。

如果可选*环体参数,它是一段Tcl脚本,对查询结果中的每一行执行一次。(环体*如果给定的命令不是选择)当前行的列的值在每次迭代之前存储到Tcl变量或数组元素中。例如:

spi_exec -array C "SELECT * FROM pg_class" {
    elog DEBUG "have table $C(relname)"
}

将为每一行打印一条日志消息pg_类。此功能的工作原理与其他Tcl循环结构类似;特别地持续打破以通常的方式在环体内工作。

如果查询结果的一列为null,则该列的目标变量为“unset”,而不是设置。

准备好了吗 查询 类型列表

准备并保存查询计划,以便以后执行。保存的计划将在当前会话期间保留。

查询可以使用参数,即在实际执行计划时提供的值的占位符。在查询字符串中,通过符号引用参数$1 ... $*n*。如果查询使用参数,则必须以Tcl列表的形式给出参数类型的名称。(写一个空的清单给*类型列表*如果未使用任何参数。)

来自的返回值准备好了吗是要在对的后续调用中使用的查询IDspi_execp看见spi_execp举个例子。

``spi_execp?-数*n*? ?-阵列*名称*? ?-空值*一串*? *奎利德* ?*价值清单*? ?*环体*?

执行以前使用准备的查询准备好了吗. *奎利德身份证是通过准备好了吗。如果查询引用参数,则价值清单必须提供。这是参数实际值的Tcl列表。列表的长度必须与之前给定给的参数类型列表的长度相同准备好了吗省略价值清单*如果查询没有参数。

的可选值-空值是一串空格和“不”角色讲述spi_execp哪些参数是空值。如果给定,则其长度必须与*价值清单*.如果未给出,则所有参数值均为非空。

除了指定查询及其参数的方式,spi_execp就像高级执行官这个-数, -阵列和*环体*选项是一样的,结果值也是一样的。

下面是一个使用准备好的计划的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;

我们需要在给定的查询字符串中使用反斜杠准备好了吗确保$*n*标记将传递给准备好了吗原样,不被Tcl变量替换所取代。

次转换 命令

中包含的Tcl脚本*命令*在SQL子事务中执行。如果脚本返回错误,则在将错误返回到周围的Tcl代码之前,将回滚整个子事务。看见第44.9节有关更多详细信息和示例。

引用 一串

将给定字符串中出现的所有单引号和反斜杠字符加倍。这可以用于安全地引用要插入到给定给的SQL命令中的字符串高级执行官准备好了吗.例如,考虑一个SQL命令字符串,如:

"SELECT '$val' AS ret"

Tcl变量瓦尔实际上包含。这将产生最终的命令字符串:

SELECT 'doesn't' AS ret

这会在运行期间导致分析错误高级执行官准备好了吗。要正常工作,提交的命令应包含:

SELECT 'doesn''t' AS ret

可通过以下方式在PL/Tcl中形成:

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

优势之一spi_execp您不必像这样引用参数值,因为这些参数永远不会作为SQL命令字符串的一部分进行解析。

埃洛格 数量 味精

发出日志或错误消息。可能的水平是调试, 日志, 信息, 注意, 警告, 错误致命的. 错误引发错误条件;如果周围的Tcl代码没有捕捉到这一点,错误就会传播到调用查询,导致当前事务或子事务中止。这实际上与Tcl相同错误命令致命的中止事务并导致当前会话关闭。(在PL/Tcl函数中使用这个错误级别可能没有充分的理由,但它是为了完整性而提供的。)其他级别只生成不同优先级的消息。特定优先级的消息是报告给客户端、写入服务器日志,还是两者都由日志_闵_信息客户_闵_信息配置变量。看见第20章第44.8节了解更多信息。