SPI_execute — 执行命令
int SPI_execute(const char *command, boolread_only, longcount)
SPI_execute 为 count 行执行指定的 SQL 命令。如果 read_only 为 true,则该命令必须是只读的,并且执行开销会略微减少。
此函数只能从已连接的 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_only 为 false 时,SPI_execute 在执行字符串中的每个命令之前,会递增命令计数器并计算一个新的快照。 如果当前事务隔离级别是 SERIALIZABLE 或 REPEATABLE READ,则快照实际上不会更改,但在 READ COMMITTED 模式下,快照更新允许每个命令查看来自其他会话的新提交事务的结果。 当命令正在修改数据库时,这对于保持一致的行为至关重要。
当 read_only 为 true 时,SPI_execute 不会更新快照或命令计数器,并且只允许命令字符串中出现纯 SELECT 命令。 这些命令使用先前为周围查询建立的快照执行。 由于消除了每个命令的开销,这种执行模式比读/写模式快一些。 它还允许构建真正的稳定函数:由于连续的执行都将使用相同的快照,因此结果不会发生变化。
通常,在单个函数中使用 SPI 混合只读和读写命令是不明智的。这可能会导致非常混乱的行为,因为只读查询将看不到读写查询所做的任何数据库更新的结果。
(最后一个)命令执行的实际行数在全局变量 SPI_processed 中返回。如果函数的返回值是 SPI_OK_SELECT、SPI_OK_INSERT_RETURNING、SPI_OK_DELETE_RETURNING、SPI_OK_UPDATE_RETURNING 或 SPI_OK_MERGE_RETURNING,那么可以使用全局指针 SPITupleTable *SPI_tuptable 来访问结果行。 一些实用程序命令(例如 EXPLAIN)也返回行集,并且 SPI_tuptable 在这些情况下也会包含结果。 一些实用程序命令(COPY、CREATE 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;
字段 tupdesc、vals 和 numvals 可以被 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如果 command 为 NULL 或 count 小于 0
SPI_ERROR_COPY如果尝试了 COPY TO stdout 或 COPY FROM stdin
SPI_ERROR_TRANSACTION如果尝试了事务操作命令(BEGIN、COMMIT、ROLLBACK、SAVEPOINT、PREPARE TRANSACTION、COMMIT PREPARED、ROLLBACK PREPARED 或其任何变体)
SPI_ERROR_OPUNKNOWN如果命令类型未知(不应该发生)
SPI_ERROR_UNCONNECTED如果从未连接的 C 函数调用
所有 SPI 查询执行函数都设置 SPI_processed 和 SPI_tuptable(仅指针,不包括结构的内容)。 如果您需要跨后续调用访问 SPI_execute 或其他查询执行函数的结果表,请将这两个全局变量保存到本地 C 函数变量中。
如果您在文档中发现任何不正确、与您对特定功能的体验不符或需要进一步说明的内容,请使用此表单来报告文档问题。