| PostgreSQL 8.0.0 中文文件(轉譯自 PostgreSQL 中國 製作的簡體中文版本) | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 36. PL/Tcl - Tcl 過程語言 | Fast Forward | Next |
在 PL/Tcl 過程體裡有下面的命令可以用於從存取資料庫:
執行一個以字串形式給出的 SQL 查詢。查詢中的錯誤會導致拋出一個錯誤。 否則,spi_exec 的返回值是命令處理的行數(選出,插入,更新,或者刪除), 如果該命令是一個功能性語句則返回零。另外,如果查詢是一條SELECT 語句,那麼選出的字串按照下面描述的方法放在 Tcl 變量中。
可選的 -count 值告訴 spi_exec 在該查詢中處理的最大的行數。其效果和把查詢設置為一個游標, 然後說 FETCH n 是一樣的。
如果查詢是一個SELECT語句,那麼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 結果中的每一行執行一次 (注意:如果給出的查詢不是 SELECT,那麼忽略 loop-body)。 在每次迭代之前,目前行的字串的數值都儲存到 Tcl 變量中去了。比如,
spi_exec -array C "SELECT * FROM pg_class" {
elog DEBUG "have table $C(relname)"
}將為 pg_class 的每一行打印一行日誌訊息。 這個特性和其它 Tcl 循環構造的運做方式類似;特別是 continue 和 break 在循環體中的作用和平常是一樣的。
如果一個查詢結果的某個字串是 NULL,那麼其目標變量就是 "unset" 而不會設置上什麼東西.
為後面的執行準備並保存一個查詢規劃。保存的規劃的生命期就是目前會話的生命期。
查詢可以使用參數,這些參數是規劃實際執行的時候提供的數值的佔位符。 在查詢字串裡用符號 $1 ... $n 引用各個參數。如果查詢使用了參數,那麼參數類型名必需以一個 Tcl 列資料表的形式給出。 (如果沒有使用參數,那麼給 typelist 寫一個空列資料表。) 目前,參數類型必需和 pg_type 裡顯示的內部類型名一樣; 比如是int4 而不是 integer。
spi_prepare 的返回值是一個可以在隨後的 spi_execp 調用中使用的查詢 ID。參閱 spi_execp 獲取例子。
執行一個前面用 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 的變量代換替換掉。
如果該查詢是單行INSERT, 返回最後的 spi_exec 或者 spi_execp 查詢插入的行的 OID。(如果不是,您收到零。)
在給出的字串裡將所由單引號和反斜槓字元複製成雙份。 它可以用於安全地處理那些要輸入到 spi_exec 或者 spi_prepare 中的 SQL 命令中的引號包圍字串。 比如,假如一個 SQL 命令看起來像這樣
"SELECT '$val' AS ret"
這裡的 Tcl 變量val實際上包含 doesn't。 這樣最後的命令字串會是這樣
SELECT $q$doesn't$q$ AS ret
而這個字串在 spi_exec 或 spi_prepare 的時候會導致一個分析錯誤。 為了能工作正常,提交的命令應該包含
SELECT 'doesn''t' AS ret
我們在 PL/Tcl 中可以這樣構造
"SELECT '[ quote $val ]' AS ret"
spi_execp 的一個優點是您不需要像這樣引號包圍參數值, 因為參數絕不會當做 SQL 查詢字串的一部分被分析。
發出一個日誌或者錯誤消息。可能的級別是 DEBUG, LOG,INFO, NOTICE,WARNING, ERROR,和 FATAL。 ERROR 拋出一個錯誤條件:該行數進一步的執行將終止, 同時退出目前交易。 FATAL 退出目前交易並且導致目前會話關閉(可能在 PL/Tcl 函數里沒有什麼理由使用這個錯誤級別, 提供它主要是為了完整)。 某個優先級別的訊息是報告給客戶端還是寫到伺服器日誌, 還是兩個都做是由 log_min_messages 和 client_min_messages 配置變量控制的。 參閱 Section 16.4 獲取更多細節。