PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

42.8. PL/Tcl 中的错误处理 #

PL/Tcl 函数内部或由其调用的 Tcl 代码可以通过执行某些无效操作、 或使用 Tcl error 命令或 PL/Tcl 的 elog 命令生成错误来抛出错误。 这类错误可以在 Tcl 内用 Tcl 的 catch 命令 捕获。如果错误未被捕获而被允许传播到 PL/Tcl 函数执行的顶层, 它会作为该函数调用查询中的一个 SQL 错误被报告。

反过来,发生在 PL/Tcl 的 spi_exec、spi_prepare 和 spi_execp 命令内部的 SQL 错误会被报告为 Tcl 错误,因此可以被 Tcl 的 catch 命令 捕获。 (这些 PL/Tcl 命令各自在一个子事务中运行其 SQL 操作,出错时该 子事务会被回滚,从而任何部分完成的操作都会被自动清理。) 同样,如果错误未被捕获而传播到顶层,它会转变回一个 SQL 错误。

Tcl 提供了一个 errorCode 变量,它能够以 Tcl 程序易于解释的形式表示关于错误的额外信息。 其内容是 Tcl 列表格式,第一个词标识报告错误的子系统或库;除此之外 的内容由各个子系统或库自行决定。 对于由 PL/Tcl 命令报告的数据库错误,第一个 词是 POSTGRES,第二个词是 PostgreSQL 版本号,更多的词是提供关于错误的详细信息的字段名/值对。 字段 SQLSTATE、condition 和 message 总是会提供 (前两个表示 Appendix A 所示的错误代码和 条件名)。 可能出现的字段包括 detail、hint、 context、 schema、table、 column、 datatype、constraint、 statement、cursor_position、 filename、lineno 和 funcname。

处理 PL/Tcl 的 errorCode 信息的一种便捷方式是把它加载到一个数组中,使字段名成为数组 下标。完成这一点的代码可能形如

if {[catch { spi_exec $sql_command }]} {
    if {[lindex $::errorCode 0] == "POSTGRES"} {
        array set errorArray $::errorCode
        if {$errorArray(condition) == "undefined_table"} {
            # deal with missing table
        } else {
            # deal with some other type of SQL error
        }
    }
}

(双冒号显式地指定 errorCode 是一个全局变量。)