PostgreSQL 9.4.4 中文手册
上一页 | 上一级 |  | 下一页

# SPI_execute

## 名称

SPI_execute -- 执行一条命令

## 大纲

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

## 描述

`SPI_execute`执行声明的 SQL 命令获取`count` 行。如果`read_only`为`true`，命令必须是只读的， 因此可以略微降低一些执行的开销。

这个函数只能在已连接的过程中调用。

如果`count`是零，则在命令适合的所有行上执行。 如果`count`大于 0 ，那么将不会超过 `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行，因为在检索到第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`，那么你可以使用全局指针 `SPITupleTable *SPI_tuptable`访问结果行。一些实用命令 (比如`EXPLAIN`)还返回行集合，并且`SPI_tuptable` 也将在这种情况下包含结果。一些实用命令（`COPY`, `CREATE TABLE AS`） 并不返回行集，所以`SPI_tuptable`为NULL，但是它们仍然返回 `SPI_processed`中处理了的行数。

结构`SPITupleTable`是这样定义的：

    typedef struct
    {
        MemoryContext tuptabcxt;    /* memory context of result table */
        uint32      alloced;        /* number of alloced vals */
        uint32      free;           /* number of free vals */
        TupleDesc   tupdesc;        /* row descriptor */
        HeapTuple  *vals;           /* rows */
    } SPITupleTable;

`vals`是一个指向数据行的的指针数组(有效记录的数目由 `SPI_processed`给出)。`tupdesc`是一个行描述符， 你可以传递给 SPI 函数处理这些数据行。`tuptabcxt`、 `alloced`和`free`是 SPI 的内部字段， 并非给 SPI 调用者使用的。

`SPI_finish`释放所有在当前过程中分配的`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_INSERT_RETURNING`

  如果执行了一条`INSERT RETURNING`

`SPI_OK_DELETE_RETURNING`

  如果执行了一条`DELETE RETURNING`

`SPI_OK_UPDATE_RETURNING`

  如果执行了一条`UPDATE 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`

  如果从一个未连接的过程中调用

## 注意

所有SPI查询执行函数设置了`SPI_processed`和`SPI_tuptable` (只是一个指针，不是结构的内容)。如果你需要跨越后面的调用访问`SPI_execute` 或者另一个查询执行函数的结果表，那么需要把这两个全局变量保存到一个局部过程变量中。

上一页 | 起始页 | 下一页
SPI_pop | 上一级 | SPI_exec