PL/pgSQL是一种块结构语言,函数定义的所有文本都必须在一个块内,其中块中的每个声明和每条语句 都是以分号结束,如果某一子块在另外一个块内,那么该子块的END关键字后面必须以分号结束,不过 对于函数体的最后一个END关键字,分号可以省略,如: [ <<label>> ]
所有在块里使用的变量都必须在块的声明段里先进行声明,唯一的例外是FOR循环里的循环计数变量, 该变量被自动声明为整型。变量声明的语法如下: variable_name [ CONSTANT ] variable_type [ NOT NULL ] [ { DEFAULT | := } expression ];
工作中可能会存在业务比较复杂,重复性工作比较多,需要批量处理数据的情况,此时使用存储过程会方便很多,存储过程的执行效率也会快很多,能帮助我们节省很多代码和时间。
以一个带简单赋值、出入参、变量有默认值的普通函数为例,分析执行过程。触发器等其他函数的执行过程大同小异,核心流程基本不变,就是多了几个默认工具变量。相比《Postgresql源码(46)plpgsql中的变量类型及对应关系》这篇总结更清晰简单。
对于事务系统来说,内层函数、外层函数都在一个事务中,内层提交就等于把事务提交了,所以外层数据也在。
Postgresql中PLPGSQL支持动态拼接SQL并执行: https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN 例如:
总结:函数入参赋值是遍历datums中需要值的变量,然后按顺序拿fcinfo->args数组的值。
PostgreSQL中的存储过程不支持使用savepoint、rollback to。原因是PG的存储过程中,异常处理使用子事务来实现的,也就是一旦发生异常,当前procedure的begin块中执行过的所有语句都会直接回滚:
1、编译过程主要是pl_gram.y做语法匹配的过程plpgsql_yyparse,整体匹配后的结果会作为PLpgSQL_stmt_block结构记录在plpgsql_parse_result中。
这篇写的细节比较多有点乱,大体流程和总结可以看第三、四篇 《Postgresql源码(49)plpgsql函数编译执行流程分析总结》和《Postgresql源码(53)plpgsql语法解析关键流程、函数分析》
Postgresql的plpgsql提供了一套钩子函数支持运行时动态加载,非常便于调试plpgsql。本文总结使用方法和实例。
进入plpgsql_parse_err_condition返回exception_label_map数组中的匹配元素:
调用SPI_execute_plan_extended执行后,可以看到tstore中有了两条结果。
整理plpgsql_Datums(解析后的变量)("无"表示该类型没有这个配置项)
plpgsql_yylex等价于server端的base_yylex,都是在lex的基础上做了封装用于获取一个token。
1、PLpgSQL_datum.dtype共有5中类型,其中2中类型属于通用类型,覆盖pg_type中所有类型:由plpgsql_build_variable函数根据pg_type中查到的类型决定(对应关系见下表中的PLPGSQL_DTYPE_VAR、PLPGSQL_DTYPE_REC)
cur cursor for select * from t10 order by f1;
curs4的在exec_stmt_open中被创建出来,创建时使用CreatePortal返回一个游标Portal:
select 列名1,列名2 into 变量1,变量2 这类调用形式的代码执行细节分析记录。
Oracle中集合类型覆盖了Postgresql数组的功能,在Oracle用户中时非常常用的。
Postgresql中支持两种行类型,两种类型使用上有一些区别,本篇结合实例简单介绍。
PostgreSQL的PLpg/SQL中任何语句的运行,都需要记录运行时的状态信息。在SQL层的执行器中运行时状态使用EState记录,在PL中状态信息使用PLpgSQL_execstate结构记录。
下面四个问题基本将市面上基于postgresql实现package的方法分成了几类。
本文探索raise notice 'sqlstate: %', sqlstate;时,%的值是怎么拿到的。
(为什么进入BLOCK每次都要走一遍赋初值流程?哪里决定的哪些变量需要赋值?《Postgresql源码(79)plpgsql中多层调用时参数传递关键点分析(pl参数)》:问题五)
《Postgresql源码(77)plpgsql中参数传递和赋值(pl参数)》 《Postgresql源码(78)plpgsql中调用call proc()时的参数传递和赋值(pl参数)》 总结 调用者在exec_stmt_call中拼接ParamListInfo传给SPI去执行call xxxx命令。 ParamListInfo记录了PL的一些回调函数,在SPI会走到:ExecuteCallStmt ExecuteCallStmt核心流程两步: 拼参数列表:会拿到所有入参 假设第一个入参是
AtSubCommit_Portals(mySubid=4) 开始处理portal:
问题一:外层ExecuteCallStmt用什么构造参数列表fcinfo->args? 问题二:外层ExecuteCallStmt如何fcinfo->args构造流程? 问题三:内层ExecuteCallStmt用什么构造fcinfo->args? 问题四:内层ExecuteCallStmt如何fcinfo->args构造流程? 问题五:exec_stmt_block刚进入初始化哪些变量? 问题六:exec_stmt_block刚进入为什么要初始化哪些变量直接用不行吗? 问题七:内层函数执行完的变量是在哪赋给外层的?
GCC上古版本(3.4)还有yacc,学习GCC如何实现if else 嵌套的问题。即:
因为在事务中,有些行为是需要看到最新数据的,比如一个RR事务拿到一个快照后执行了一段时间,这时运行了一条CALL Func或触发器语句,开始进入函数的执行逻辑。
注意到SPI_rollback后,使用plpgsql_create_econtext重建了eval_econtext:
参考实例1的分析结果,commit执行完了会新起一个事务,后面的保存不影响前面已经提交的事务了。
前言 Postgresql中包含两类setof函数: SQL函数:https://www.postgresql.org/docs/current/xfunc-sql.html PLPGSQL函数:https://www.postgresql.org/docs/current/plpgsql-control-structures.html#PLPGSQL-STATEMENTS-RETURNING 本文只关注PLPGSQL中的return setof的使用方法。 总结 假设类型foo存在 DROP TABLE
在PL/pgSQL语言中,执行任何SQL都需要通过SPI调用SQL层解析执行,例如在SQL层执行表达式的入口:
Postgresql与Oracle都是扁平化处理函数内外的事务控制语句的:即函数内的commit也会直接把函数外面的语句提交掉,函数外面的commit也会把之前函数内部的语句提交掉。
oracle支持pipelined函数,可以在函数定义时指定RETURN 集合类型 PIPELINED 来说明当前函数是管道函数。
Postgresql支持变长参数传递,参数被自动转换为数据传入函数体中,类似C语言的可变参数:int sum(int num_args, ...)。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wzy0623/article/details/89051688
一句话总结:函数报错后,SPI的内存不会释放,只会把_SPI_current置空(AtEOXact_SPI);因为内存是挂在TopTransactionContext下面的。等着事务提交后,一起释放(AtCleanup_Memory)。
未来的数据库发展一定是往云上发展的,倒不是云有什么好,主要还是成本的因素,成本因素比较复杂,这里不探讨,如果你单单认为只是一些机房等基础那就大大的错误了,有机会在探讨为什么以后DBA 大多都不会触及一些基础的数据库架构,要在云上去进行新一代的DBA 生涯了。
pg_plan_queries→pg_plan_query→planner→standard_planner→subquery_planner→preprocess_expression
pl/pgsql即Procedural Language/ Postgres SQL(过程化sql语言),是Postgresql数据库对sql语句的扩展,可以在pl/pgsql代码块内定义多条sql语句,每条语句以分号结束,代码块由begin开始,end结束,代码块的最后一个end可以不加分号。
游标一般适用于大结果集,大结果集在内存中放不下 且 数据可以一条一条处理的情况 比较适合使用游标。
Postgresql中写C函数时,如果函数有out类型的参数,在C代码中 是 无法 为Out参数配置值的,因为return只能配置返回值无法配置out值,这是PG的框架问题,我们可以想办法规避。
注意PG_CATCH和PG_FINALLY是二选一的,区别是PG_FINALLY会在最后把异常重新抛出去,而PG_CATCH自己处理完了就不在向上抛了。
PostgreSQL 的存储过程在POSTGRESQL 11 有了改变,从统一的 create function 到 create procedure 到底能从中获得什么
领取专属 10元无门槛券
手把手带您无忧上云