On this page
SPI_execute
SPI_execute —执行命令
Synopsis
int SPI_execute(const char * command, bool read_only, long count)
Description
SPI_execute
对* count
行执行指定的 SQL 命令。如果 read_only
*是true
,则该命令必须是只读的,并且执行开销会有所减少。
该函数只能从连接的过程中调用。
如果* 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
命令出现在命令字符串中。使用先前为周围查询构建的快照执行命令。由于消除了每个命令的开销,因此该执行模式比读/写模式要快一些。它还允许构建 true 的 stable *函数:由于连续执行都将使用相同的快照,因此结果不会发生变化。
使用 SPI 在一个函数中混合使用只读和读写命令通常是不明智的。这可能会导致非常混乱的行为,因为只读查询将看不到读写查询完成的任何数据库更新的结果。
已执行(最后一个)命令的实际行数在全局变量SPI_processed
中返回。如果函数的返回值为SPI_OK_SELECT
,SPI_OK_INSERT_RETURNING
,SPI_OK_DELETE_RETURNING
或SPI_OK_UPDATE_RETURNING
,则可以使用全局指针SPITupleTable *SPI_tuptable
来访问结果行。一些 Util 命令(例如EXPLAIN
)也会返回行集,在这些情况下SPI_tuptable
也将包含结果。某些 Util 命令(COPY
,CREATE TABLE AS
)不返回行集,因此SPI_tuptable
为 NULL,但它们仍返回SPI_processed
中处理的行数。
因此定义结构SPITupleTable
:
typedef struct
{
MemoryContext tuptabcxt; /* memory context of result table */
uint64 alloced; /* number of alloced vals */
uint64 free; /* number of free vals */
TupleDesc tupdesc; /* row descriptor */
HeapTuple *vals; /* rows */
} SPITupleTable;
vals
是指向行的指针的数组。 (有效条目的数量由SPI_processed
给出.)tupdesc
是行 Descriptors,您可以将其传递给处理行的 SPI 函数。 tuptabcxt
,alloced
和free
是 SPI 调用程序不打算使用的内部字段。
SPI_finish
释放当前过程中分配的所有SPITupleTable
。如果完成了特定的结果表,则可以调用SPI_freetuptable
来释放它。
Arguments
const char * command
- 包含要执行的命令的字符串
bool read_only
true
用于只读执行
long count
- 要返回的最大行数,或
0
无限制
- 要返回的最大行数,或
Return Value
如果命令执行成功,则将返回以下(负值)值之一:
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_INSERT_RETURNING
- 如果执行了
INSERT RETURNING
- 如果执行了
SPI_OK_DELETE_RETURNING
- 如果执行了
DELETE RETURNING
- 如果执行了
SPI_OK_UPDATE_RETURNING
- 如果执行了
UPDATE RETURNING
- 如果执行了
SPI_OK_UTILITY
- 如果执行了 Util 命令(例如
CREATE TABLE
)
- 如果执行了 Util 命令(例如
SPI_OK_REWRITTEN
- 如果该命令被rule重写为另一种命令(例如
UPDATE
成为INSERT
)。
- 如果该命令被rule重写为另一种命令(例如
错误时,将返回以下负值之一:
SPI_ERROR_ARGUMENT
- 如果*
command
为NULL
或count
*小于 0
- 如果*
SPI_ERROR_COPY
- 如果尝试了
COPY TO stdout
或COPY FROM stdin
- 如果尝试了
SPI_ERROR_TRANSACTION
- 如果尝试了 Transaction 操作命令(
BEGIN
,COMMIT
,ROLLBACK
,SAVEPOINT
,PREPARE TRANSACTION
,COMMIT PREPARED
,ROLLBACK PREPARED
或其任何变体)
- 如果尝试了 Transaction 操作命令(
SPI_ERROR_OPUNKNOWN
- 如果命令类型未知(不应发生)
SPI_ERROR_UNCONNECTED
- 如果从未连接的过程调用
Notes
所有 SPI 查询执行功能都设置SPI_processed
和SPI_tuptable
(仅是指针,而不是结构的内容)。如果需要在以后的调用中访问SPI_execute
的结果表或另一个查询执行函数,请将这两个全局变量保存到本地过程变量中。