2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 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;

欄位 tupdescvalsnumvals 可以由 SPI 呼叫者使用;其餘欄位是內部使用的。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 函式變數中。

提交更正

如果您在文件中發現任何不正確、與您對特定功能的經驗不符或需要進一步澄清的內容,請使用 此表單 報告文件問題。