🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# SPI_prepare ## Name SPI_prepare -- 准备一个规划但不立即执行它 ## Synopsis ``` SPIPlanPtr SPI_prepare(const char * command, int nargs, Oid * argtypes) ``` ## 描述 `SPI_prepare`为声明的命令创建和返回一个预备语句但是不执行查询。 该预备语句稍后可以使用`SPI_execute_plan`重复的执行。 如果相同或者类似的查询要多次重复执行,那么通常只进行一次解析分析应该是更好些, 并且此外可能有利于为该命令重复使用一个执行规划。`SPI_prepare` 把一个命令字符串转换成一个封装解析分析的结果的预备语句。 如果发现为每个执行生成一个自定义规划没什么帮助, 那么该预备语句也为缓存一个执行规划提供位置。 可以把预编写的查询通用化,方法是在那些普通查询里是常量的地方书写参数 (`$1`, `$2`等等)。参数的数值随后在调用`SPI_execute_plan` 的时候声明。这样就允许已准备的查询在远比没有参数时广泛得多的场合下使用。 `SPI_prepare`返回的语句只能在当前过程调用中使用, 因为`SPI_finish`释放为这样一个语句分配的内存。不过, 一个语句可以用函数`SPI_keepplan`或`SPI_saveplan` 保存更长的时间。 ## 参数 `const char *` `command` 命令字符串 `int` `nargs` 输入参数的个数(`$1`, `$2`等等) `Oid *` `argtypes` 一个指针,指向包含参数数据类型的OID数组 ## 返回值 `SPI_prepare`返回一个指向一个`SPIPlan`的非空指针, `SPIPlan`是一个表示预备语句的不透明结构。错误时将返回`NULL`, 并且`SPI_result`将设置为和`SPI_execute` 使用的同样错误的错误代码,例外是在`command`是 `NULL`的时候,或者是`nargs`小于 0 或者`nargs` 大于 0 并且`argtypes`是`NULL`的时候会被设置成 `SPI_ERROR_ARGUMENT`。 ## 注意 如果没有定义参数,那么在第一次使用`SPI_execute_plan` 时将创建一个通用规划,并且也用于所有随后的执行。如果有参数, 前几次使用`SPI_execute_plan`将生成特定于提供的参数值的自定义规划。 相同的预备语句使用足够多次之后,`SPI_execute_plan` 将建立一个通用规划,并且如果该通用规划并不比自定义规划昂贵的多的话, 它将开始使用该通用规划而不是每次重新规划。如果这个缺省行为不合适, 你可以通过传递`CURSOR_OPT_GENERIC_PLAN`或`CURSOR_OPT_CUSTOM_PLAN` 标志到`SPI_prepare_cursor`来修改它,分别强制使用通用或自定义规划。 尽管预备语句的要点是为了避免重复的解析分析和规划语句, 但是在语句中使用的数据库对象自上次使用预备语句以来经历了明确的(DDL) 改变时,PostgreSQL将在使用它之前强制重新分析和重新规划语句。 另外,如果[search_path](#calibre_link-738)的值在下一次使用时发生了改变时, 该语句将使用新的`search_path`重新解析。(后者的行为是 PostgreSQL 9.3新增的。)参阅[PREPARE](#calibre_link-625) 获取更多关于预备语句的行为的信息。 这个函数应该只从一个已连接的过程中调用。 `SPIPlanPtr`声明为一个指针,指向`spi.h`中的一个不透明的结构类型。 尝试直接访问它的内容是不明智的,因为那样会使得你的代码在未来的 PostgreSQL修订版本中更容易破裂。 名字`SPIPlanPtr`是历史用法,因为数据结构不再需要包含一个执行规划。