PostgreSQL 從 PL/Tcl 訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)

2021-09-06 10:08 更新

下面的命令可以用來(lái)從 PL/Tcl 函數(shù)體中訪(fǎng)問(wèn)數(shù)據(jù)庫(kù):

spi_exec ?-count n? ?-array name? command ?loop-body?

執(zhí)行一個(gè)以字符串給出的 SQL 命令。命令中錯(cuò)誤將會(huì)導(dǎo)致錯(cuò)誤發(fā)生。否則,spi_exec的返回值是被命令處理的行數(shù)(選擇、插入、更新或者刪除),如果命令是一條功能性語(yǔ)句則返回零。此外,如果命令是一條SELECT語(yǔ)句,被選中的列的值會(huì)被放在上文所述的 Tcl 變量中。

可選的-count值告訴spi_exec命令中要處理的最大行數(shù)。這種效果類(lèi)似于用游標(biāo)建立一個(gè)查詢(xún)?nèi)缓笫褂?code class="literal">FETCH n 。

如果命令是一條SELECT語(yǔ)句,結(jié)果列的值會(huì)被放在以列名命名的 Tcl 變量中。如果給出了-array選項(xiàng),列值會(huì)被存儲(chǔ)在所提及的關(guān)聯(lián)數(shù)組的元素中,而列名則被用作數(shù)組索引。此外,結(jié)果中的當(dāng)前行號(hào)(從零開(kāi)始記)被存儲(chǔ)在數(shù)組元素.tupno中,除非這個(gè)名字在結(jié)果中已經(jīng)被用作一個(gè)列名。

如果命令是一條SELECT語(yǔ)句并且沒(méi)有給出loop-body腳本,則只有結(jié)果的第一行被存儲(chǔ)在 Tcl 變量或數(shù)組元素中。如果結(jié)果中有剩余的行,它們會(huì)被忽略。如果查詢(xún)不返回行則不存儲(chǔ)任何東西(這種情況可以通過(guò)spi_exec的結(jié)果檢測(cè)到)。例如:

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

將把 Tcl 變量$cnt設(shè)置為pg_proc系統(tǒng)目錄中的行數(shù)。

如果給出了可選的loop-body參數(shù),它會(huì)是一個(gè) Tcl 腳本,對(duì)查詢(xún)結(jié)果中的每一行都要執(zhí)行這個(gè)腳本(如果給出的查詢(xún)不是SELECT則忽略loop-body)。在每次迭代前當(dāng)前行的列值會(huì)被存儲(chǔ)在 Tcl 變量或數(shù)組元素中。例如:

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

會(huì)對(duì)pg_class的每一行打印一段日志消息。這種特性工作起來(lái)類(lèi)似于其他的 Tcl 循環(huán)結(jié)構(gòu)。特別是continuebreak的動(dòng)作方式與在循環(huán)體中的通常方式相同。

如果一個(gè)查詢(xún)結(jié)果的一列為空,為它準(zhǔn)備的目標(biāo)變量不會(huì)被建立,而是會(huì)被unset。

spi_prepare query typelist

為后面的執(zhí)行準(zhǔn)備并且保存一個(gè)查詢(xún)計(jì)劃。保存下來(lái)的計(jì)劃將在當(dāng)前會(huì)話(huà)的生命期內(nèi)保持存在。

查詢(xún)可以使用參數(shù),也就是占位符。在計(jì)劃真正被執(zhí)行時(shí)將會(huì)為占位符提供值。在查詢(xún)字符串中,可以用符號(hào)$1 ... $n 引用參數(shù)。如果查詢(xún)使用了參數(shù),參數(shù)類(lèi)型的名稱(chēng)必須以一個(gè) Tcl 列表的形式給出(如果不使用參數(shù),可以為typelist寫(xiě)一個(gè)空列表)。

spi_prepare返回的值是一個(gè)查詢(xún) ID,在后續(xù)的spi_execp調(diào)用中需要用到這個(gè) ID。例子可見(jiàn)spi_execp。

spi_execp ?-count n? ?-array name? ?-nulls string? queryid ?value-list? ?loop-body?

執(zhí)行一個(gè)之前用spi_prepare準(zhǔn)備的查詢(xún)。queryidspi_prepare返回的 ID。如果查詢(xún)引用參數(shù),則必須提供一個(gè)value-list。這是一個(gè)參數(shù)實(shí)際值的 Tcl 列表。這個(gè)列表必須和之前傳給 spi_prepare的參數(shù)類(lèi)型列表具有相同的長(zhǎng)度。如果查詢(xún)沒(méi)有參數(shù)則可省略value-list。

-nulls的值可選,它是一個(gè)空格和'n'字符構(gòu)成的串,它告訴spi_execp哪些參數(shù)是空值。如果給出這個(gè)值,它必須正好和value-list長(zhǎng)度相等。如果沒(méi)有給出這個(gè)值,所有的參數(shù)值都是空。

除了指定查詢(xún)及其參數(shù)的方法,spi_execpspi_exec很像。-count、-array以及loop-body選項(xiàng)是相同的,并且結(jié)果值也一樣。

這里是一個(gè)使用預(yù)備計(jì)劃的 PL/Tcl 函數(shù)的例子:

CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS $$
    if {![ info exists GD(plan) ]} {
        # 第一次調(diào)用時(shí)準(zhǔn)備保存的計(jì)劃
        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的查詢(xún)字符串里放上反斜線(xiàn)來(lái)確保$n 標(biāo)記會(huì)被原樣傳遞給spi_prepare,并且不會(huì)被 Tcl 變量替換。

subtransaction command

command中包含的Tcl腳本會(huì)被在一個(gè)SQL子事務(wù)中執(zhí)行。如果該腳本返回一個(gè)錯(cuò)誤,那么整個(gè)子事務(wù)會(huì)在把錯(cuò)誤返回到外圍的Tcl代碼之前就回滾。更多細(xì)節(jié)和例子請(qǐng)參考第 43.9 節(jié)。

quote string

在給定的字符串中雙寫(xiě)所有單引號(hào)和反斜線(xiàn)字符。這可以被用來(lái)引用字符串,以便它們能被安全地插入到傳給spi_exec或者spi_prepare的 SQL 命令字符串中。例如,考慮這樣的 SQL 命令字符串:

"SELECT '$val' AS ret"

這里的 Tcl 變量val實(shí)際上包含doesn't。這將會(huì)導(dǎo)致最終的命令串:

SELECT 'doesn't' AS ret

這種命令串會(huì)導(dǎo)致spi_execspi_prepare期間的解析錯(cuò)誤。要正確地工作,提交的命令應(yīng)該包含:

SELECT 'doesn''t' AS ret

在 PL/Tcl 中可以這樣做:

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

spi_execp的一個(gè)好處是你不必這樣引用參數(shù)值,因?yàn)閰?shù)值不會(huì)被作為 SQL 命令串的一部分被解析。

elog level msg

發(fā)出一段日志或者錯(cuò)誤消息。可能的級(jí)別是DEBUG、LOGINFO、NOTICE、WARNING、ERROR以及FATAL。 ERROR產(chǎn)生一個(gè)錯(cuò)誤情況。如果周?chē)?Tcl 代碼沒(méi)有捕捉它,錯(cuò)誤會(huì)傳播到調(diào)用查詢(xún),導(dǎo)致當(dāng)前事務(wù)或者子事務(wù)被中止。這實(shí)際上與 Tcl 的error命令相同。FATAL中止事務(wù)并且導(dǎo)致當(dāng)前會(huì)話(huà)關(guān)閉(可能在 PL/Tcl 函數(shù)中沒(méi)有很好的理由來(lái)使用這種錯(cuò)誤級(jí)別,但是為了完整性還是提供了這種級(jí)別)。其他級(jí)別只產(chǎn)生不同優(yōu)先級(jí)的消息。一個(gè)特定級(jí)別的消息是被報(bào)告給客戶(hù)端、寫(xiě)入到服務(wù)器日志或者兩者都做,是由配置變量 log_min_messagesclient_min_messages所控制。詳見(jiàn)第 19 章第 43.8 節(jié)。


以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)