名称
PREPARE -- 创建一个预备语句
语法
PREPARE name [ (datatype [, ...] ) ] AS statement
描述
PREPARE 创建一个预备语句。一个预备语句是服务器端的对象,可以用于优化性能。在执行 PREPARE 语句的时候,指定的查询被分析、重写、规划。当随后发出 EXECUTE 语句的时候,预备语句就只需要执行了。因此,分析、重写、规划阶段都只执行一次,而不是每次都要执行一次。
预备语句可以接受参数:在它执行的时候替换到查询中的数值。可以在一个预备语句里按照位置来引用参数,比如 $1, $2 等。可以指定一个相应的参数数据类型列表。如果一个参数的数据类型没有被指定或声明为 unknown ,那么其类型将根据该参数所使用的实际上下文环境进行推测(如果有可能的话)。当执行该语句的时候,将在 EXECUTE 语句中为这些参数指定实际值。参见 EXECUTE 获取更多信息。
预备语句只是在当前数据库会话的过程中存在。如果客户端退出,那么预备语句就会被遗忘,因此必须在被重新使用之前重新创建。这也意味着一个预备语句不能被多个数据库客户端同时使用;但是,每个客户端可以创建它们自己的预备语句来使用。预备语句可以用 DEALLOCATE 命令手工清除。
如果一个会话准备用于执行大量类似的查询,那么预备语句可以获得最大限度的性能优势。如果查询非常复杂,需要复杂的规划或者重写,那么性能差距将更加明显。比如,如果查询设计许多表的连接,或者有多种规则要求应用。如果查询的规划和重写相对简单,而执行起来开销相当大,那么预备语句的性能优势就不那么明显。
参数
name
给予这个特定的预备语句任意名字。它必须在一个会话中是唯一的,并且用于执行或者删除一个预备语句。
datatype
预备语句的某个参数的数据类型。如果某个参数的数据类型未指定或指定为 unknown ,那么将根据该参数使用的上下文环境进行推断。可以使用 $1, $2 等等在预备语句内部引用这个参数。
statement
SELECT, INSERT, UPDATE, DELETE, VALUES 语句之一
注意
在一些情况下,PostgreSQL 为一个预备语句生成的查询规划可能还不如按照普通方法提交并执行的查询生成的规划好。这是因为该查询在被规划的时候(也是优化器判断最优查询规划的时候),在查询中声明的任何参数的实际数值都还不可见。PostgreSQL 在表中收集数据分布的统计,而且可以利用查询中的常量来猜测执行查询的可能结果。因为这些数据在规划的时候还是未知,所以,得到的规划可能很差劲。使用 EXPLAIN 查看 PostgreSQL 为预备语句选取的查询计划。
有关查询规划和 PostgreSQL 为查询优化的目的收集统计的更多信息,参阅 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 语句创建一个预备语句然后执行它:
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);
注意,第二个参数的数据类型并未指定。所以将从上下文环境推测 $2 的类型。
兼容性
SQL 标准包含一个 PREPARE 语句,但是它只用于嵌入式 SQL 。PostgreSQL 实现的 PREPARE 语句的语法也略有不同。
又见
个人例子:
create table a (
a_1 int4,
a_2 text,
a_3 boolean,
a_4 numeric
)
PREPARE aplan (int, text, bool, numeric) AS
INSERT INTO aigw.a VALUES($1, $2, $3, $4);
EXECUTE aplan(1, 'Hunter Valley', 't', 200.00);
PREPARE aselect (int) AS
SELECT * FROM aigw.a WHERE a.a_1=$1;
EXECUTE aselect(1);
可以在函数中使用如下语句 执行 sql
执行转换存储过程
-- 拼接SQL
v_excute_sql := concat('select * from phis61.', v_rec_task.zx2phisprocname, '($1);');
select row_to_json(v_rec_task) into v_jsonb_uploadtask;
-- 执行SQL
EXECUTE v_excute_sql INTO v_rec USING v_jsonb_uploadtask;
v_的变量为 Function declare 声明的变量
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于