在本節中,我們遵循 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,則其目標變數將被“取消設定”而不是被設定。
spi_prepare
query
typelist
準備並儲存一個查詢計劃以供稍後執行。儲存的計劃將在當前會話的生命週期內保留。
查詢可以使用引數,即佔位符,用於在每次實際執行計劃時提供值。在查詢字串中,透過符號 $1
... $
來引用引數。如果查詢使用引數,則引數型別的名稱必須以 Tcl 列表的形式給出。(如果未使用引數,請為 n
typelist
寫入一個空列表。)
spi_prepare
的返回值是一個用於後續呼叫 spi_execp
的查詢 ID。請參閱 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
完全相同。如果未給定,則所有引數值都不是 NULL。
除了指定查詢及其引數的方式外,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 節。
如果您在文件中看到任何不正確、與您對特定功能的體驗不符或需要進一步澄清的內容,請使用 此表單 來報告文件問題。