PREPARE

最近更新时间:2019-04-22 11:25:29

为执行准备一个语句。

概要

PREPARE name [ (datatype [, ...] ) ] AS statement

描述

PREPARE 创建一个预备语句,有可能有未绑定参数。预备语句是一种服务器端对象,它可以被用来优化性能。
一个预备语句可能后续给参数绑定值后被执行。数据库可能选择对同一预备语句的不同执行进行重新规划。

预备语句可以接受参数,在执行时会被替换到语句中的值。在创建预备语句时,可以用位置引用参数,如$1、$2等。也可以选择性地指定参数数据类型的一个列表。当一个参数的数据类型没有被指定或者被声明为 unknown 时,其类型会从该参数被使用的环境中推知(如果可能)。在执行该语句时,在 EXECUTE 语句中为这些参数指定实际值。

预备语句只在当前数据库会话期间存在。当会话结束时,预备语句会消失,因此在重新使用之前必须重新建立它。这也意味着一个预备语句不能被多个数据库客户端同时使用。不过,每一个客户端可以创建它们自己的预备语句来使用。预备语句可以用 DEALLOCATE 命令手工清除。

当一个会话要执行大量类似语句时,预备语句可能会有最大性能优势。如果该语句很复杂(难于规划或重写),例如如果查询涉及很多表的连接或者要求应用多个规则,性能差异将会特别明显。如果语句相对比较容易规划和重写,但是执行起来开销相对较大,那么预备语句的性能优势就不那么显著了。

参数

name
给这个特定预备语句的任意名称。它在一个会话中必须唯一并且后续将被用来执行或者清除一个之前准备好的语句。

datatype
预备语句一个参数的数据类型。如果一个特定参数的数据类型没有被指定或者被指定为 unknown,将从该参数被使用的环境中推得。要在预备语句本身中引用参数,可以使用$1、 $2等。

statement
任何 SELECT、INSERT、UPDATE、DELETE 或者 VALUES 语句。

注解

在某些场景中,为一个预备语句产生的查询计划将比不上该语句被正常提交执行时的查询计划。这是因为当语句被规划并且规划器尝试确定最优查询计划时,该语句中指定的任何参数的实际值都还不可用。
数据库收集表中数据分布的统计信息,同时可以用语句中的常量值来猜测执行该语句的可能结果。由于在使用参数规划预备语句时,这种数据还不可用,被选中的计划可能是次优的。为了检测数据库中为预备语句选择的查询计划,可以使用 EXPLAIN。

更多关于查询规划以及数据库为此所收集的统计信息的内容,请见 ANALYZE 文档。

可以通过查询 pg_prepared_statements 系统视图来看到会话中所有可用的预备语句。

示例

为一个 INSERT 语句创建一个预备语句,然后执行它:

PREPARE fooplan (int, text, bool, numeric) AS INSERT INTO 
foo VALUES($1, $2, $3, $4);
EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00);

为一个 SELECT 语句创建一个预备语句,然后执行它。注意第二个参数的数据类型没有被指定,因此会从使用$2的环境中推知:

PREPARE usrrptplan (int) AS SELECT * FROM users u, logs l 
WHERE u.usrid=$1 AND u.usrid=l.usrid AND l.date = $2;
EXECUTE usrrptplan(1, current_date);

兼容性

SQL 标准包括一个 PREPARE 语句,但是它只用于嵌入式 SQL。这个版本的 PREPARE 语句也使用了一种有些不同的语法。

另见

EXECUTE、DEALLOCATE