支援的版本: 目前 (17) / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0

SPI_execute

SPI_execute — 執行指令

概要

int SPI_execute(const char * command, bool read_only, long count)

描述

SPI_executecount 列執行指定的 SQL 指令。如果 read_onlytrue,則該指令必須是唯讀的,且執行開銷會稍微降低。

此函數只能從已連線的 C 函數中呼叫。

如果 count 為零,則會針對它所適用的所有列執行該指令。如果 count 大於零,則最多會擷取 count 列;當達到計數時,執行會停止,這很像是在查詢中新增一個 LIMIT 子句。例如:

SPI_execute("SELECT * FROM foo", true, 5);

將從資料表中擷取最多 5 列。請注意,這種限制只有在指令實際傳回列時才有效。例如:

SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);

會插入來自 bar 的所有列,而忽略 count 參數。然而,透過

SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);

最多會插入 5 列,因為在擷取到第五個 RETURNING 結果列之後,執行將會停止。

您可以在一個字串中傳遞多個指令;SPI_execute 會傳回最後執行的指令的結果。count 限制分別適用於每個指令(即使實際上只會傳回最後一個結果)。該限制不適用於規則產生的任何隱藏指令。

read_onlyfalse 時,SPI_execute 會遞增命令計數器,並在字串中執行每個指令之前計算新的快照。如果目前的交易隔離層級是 SERIALIZABLEREPEATABLE READ,則快照實際上不會變更,但在 READ COMMITTED 模式下,快照更新允許每個指令看到來自其他工作階段的新提交交易的結果。當指令正在修改資料庫時,這對於一致的行為至關重要。

read_onlytrue 時,SPI_execute 不會更新快照或命令計數器,並且它只允許純 SELECT 指令出現在指令字串中。這些指令會使用先前為周圍查詢建立的快照來執行。由於消除了每個指令的開銷,因此這種執行模式比讀/寫模式稍微快一些。它也允許建置真正穩定的函數:由於連續的執行都將使用相同的快照,因此結果不會有任何變更。

通常不建議使用 SPI 在單一函數中混合使用唯讀和讀寫指令;這可能會導致非常混淆的行為,因為唯讀查詢將看不到讀寫查詢所做的任何資料庫更新的結果。

(最後一個)指令執行的實際列數會傳回在全域變數 SPI_processed 中。如果函數的傳回值為 SPI_OK_SELECTSPI_OK_INSERT_RETURNINGSPI_OK_DELETE_RETURNINGSPI_OK_UPDATE_RETURNINGSPI_OK_MERGE_RETURNING,則您可以使用全域指標 SPITupleTable *SPI_tuptable 來存取結果列。某些公用程式指令(例如 EXPLAIN)也會傳回列集合,而 SPI_tuptable 也會在這些情況下包含結果。某些公用程式指令(COPYCREATE TABLE AS)不會傳回列集合,因此 SPI_tuptable 為 NULL,但它們仍然會傳回 SPI_processed 中處理的列數。

結構 SPITupleTable 的定義如下

typedef struct SPITupleTable
{
    /* Public members */
    TupleDesc   tupdesc;        /* tuple descriptor */
    HeapTuple  *vals;           /* array of tuples */
    uint64      numvals;        /* number of valid tuples */

    /* Private members, not intended for external callers */
    uint64      alloced;        /* allocated length of vals array */
    MemoryContext tuptabcxt;    /* memory context of result table */
    slist_node  next;           /* link for internal bookkeeping */
    SubTransactionId subid;     /* subxact in which tuptable was created */
} SPITupleTable;

SPI 呼叫者可以使用欄位 tupdescvalsnumvals;其餘欄位是內部的。vals 是一個指向列的指標陣列。列數由 numvals 給出(由於某些歷史原因,此計數也會傳回在 SPI_processed 中)。tupdesc 是一個列描述元,您可以將其傳遞給處理列的 SPI 函數。

SPI_finish 會釋放目前 C 函數期間配置的所有 SPITupleTable。如果您已完成特定的結果表,您可以透過呼叫 SPI_freetuptable 提早釋放它。

引數

const char * command

包含要執行的指令的字串

bool read_only

針對唯讀執行為 true

long count

要傳回的最大列數,或針對沒有限制為 0

傳回值

如果指令執行成功,則將傳回下列其中一個(非負數)值

SPI_OK_SELECT

如果執行了 SELECT(但不是 SELECT INTO

SPI_OK_SELINTO

如果執行了 SELECT INTO

SPI_OK_INSERT

如果執行了 INSERT

SPI_OK_DELETE

如果執行了 DELETE

SPI_OK_UPDATE

如果執行了 UPDATE

SPI_OK_MERGE

如果執行了 MERGE

SPI_OK_INSERT_RETURNING

如果執行了 INSERT RETURNING

SPI_OK_DELETE_RETURNING

如果執行了 DELETE RETURNING

SPI_OK_UPDATE_RETURNING

如果執行了 UPDATE RETURNING

SPI_OK_MERGE_RETURNING

如果執行了 MERGE RETURNING

SPI_OK_UTILITY

如果執行了工具命令(例如 CREATE TABLE

SPI_OK_REWRITTEN

如果命令被 規則 重寫為另一種命令(例如,UPDATE 變為 INSERT)。

發生錯誤時,會傳回以下負值之一

SPI_ERROR_ARGUMENT

如果 commandNULLcount 小於 0

SPI_ERROR_COPY

如果嘗試了 COPY TO stdoutCOPY FROM stdin

SPI_ERROR_TRANSACTION

如果嘗試了事務操作命令(BEGINCOMMITROLLBACKSAVEPOINTPREPARE TRANSACTIONCOMMIT PREPAREDROLLBACK PREPARED 或其任何變體)

SPI_ERROR_OPUNKNOWN

如果命令類型未知(不應該發生)

SPI_ERROR_UNCONNECTED

如果從未連線的 C 函數呼叫

注意事項

所有 SPI 查詢執行函數都會設定 SPI_processedSPI_tuptable(僅指標,而非結構的內容)。 如果您需要在後續呼叫中存取 SPI_execute 或另一個查詢執行函數的結果表,請將這兩個全域變數儲存到本機 C 函數變數中。

提交更正

如果您在文件中看到任何不正確、與您使用特定功能的經驗不符或需要進一步澄清的地方,請使用此表單回報文件問題。