博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PostgreSQL Oracle 兼容性之 - DBMS_SQL(存储过程动态SQL中使用绑定变量)
阅读量:6894 次
发布时间:2019-06-27

本文共 7535 字,大约阅读时间需要 25 分钟。

标签

PostgreSQL , Oracle , pl/sql , 存储过程 , plpgsql , 绑定变量 , DB端绑定变量 , prepare , DEALLOCATE , EXECUTE


背景

Oracle中有一个dbms_sql的包,可以让你在存储过程的动态SQL中使用prepared statement。如果动态SQL的调用频次较高,硬解析可能导致一些性能问题(Oracle硬解析的CPU消耗还是蛮大的)。

DMBS_SQL里面包含的一些类型

Bulk SQL Types    BFILE_TABLE    BINARY_DOUBLE_TABLE    BLOB_TABLE    CLOB_TABLE    DATE_TABLE    INTERVAL_DAY_TO_SECOND_TABLE    INTERVAL_YEAR_TO_MONTH_TABLE    NUMBER_TABLE    TIME_TABLE    TIME_WITH_TIME_ZONE_TABLE    TIMESTAMP_TABLE    TIMESTAMP_WITH_LTZ_TABLE    UROWID_TABLE    VARCHAR2_TABLE

其中本文用到的 NUMBER_TABLE

TYPE number_table IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;

在PostgreSQL的INLINE CODE或者FUNCTION中如何使用动态SQL,如何使用绑定变量,如何使用BULK类型呢?

PostgreSQL INLINE CODE或函数的动态SQL、绑定变量使用

首先借这个链接,解释一下Oracle dbms_sql的使用

Better to understand DBMS_SQL itself to some extent, before understanding NUMBER_TABLE.   ( I do this for My Learning!)    NUMBER_TABLE  is Actually,    TYPE number_table IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;  So, only numbers are allowed!    FlowChart on How DBMS_SQL Works! :    Your interested area comes in bind variable box
-----------  --                    | open_cursor |  --                      -----------  --                           |  --                           |  --                           v  --                         -----  --          ------------>| parse |  --          |              -----  --          |                |  --          |                | ---------  --          |                v          |  --          |           --------------  |  --          |-------->| bind_variable | |  --          |     ^     -------------   |  --          |     |           |         |  --          |      -----------|         |  --          |                 |<--------  --          |                 v  --          |               query?---------- yes ---------  --          |                 |                           |  --          |                no                           |  --          |                 |                           |  --          |                 v                           v  --          |              -------                  -------------  --          |----------->| execute |            ->| define_column |  --          |              -------             |    -------------  --          |                 |------------    |          |  --          |                 |            |    ----------|  --          |                 v            |              v  --          |           --------------     |           -------  --          |       ->| variable_value |   |  ------>| execute |  --          |      |    --------------     | |         -------  --          |      |          |            | |            |  --          |       ----------|            | |            |  --          |                 |            | |            v  --          |                 |            | |        ----------  --          |                 |<-----------  |----->| fetch_rows |  --          |                 |              |        ----------  --          |                 |              |            |  --          |                 |              |            v  --          |                 |              |  -----------------  --          |                 |              | | column_value    |  --          |                 |              | | variable_value  |  --          |                 |              |  -----------------  --          |                 |              |            |  --          |                 |<--------------------------  --          |                 |  --           -----------------|  --                            |  --                            v  --                       ------------  --                     | close_cursor |  --                       ------------

例子

Example: In a DELETE statement, for example, you could bind in an array in the WHERE clause and have the statement be run for each element in the array:    DECLARE    stmt VARCHAR2(200);    dept_no_array DBMS_SQL.NUMBER_TABLE;    c NUMBER;    dummy NUMBER;  begin    dept_no_array(1) := 10; dept_no_array(2) := 20; /* Put some values into the array */    dept_no_array(3) := 30; dept_no_array(4) := 40;    dept_no_array(5) := 30; dept_no_array(6) := 40;    stmt := 'delete from emp where deptno = :dept_array'; /* A Dynamic SQL String with a bind variable */    c := DBMS_SQL.OPEN_CURSOR; /* Open a Cursor! */    DBMS_SQL.PARSE(c, stmt, DBMS_SQL.NATIVE); /* Parse the Dynamic SQL , making it happen on the native database to which is connected! */      DBMS_SQL.BIND_ARRAY(c, ':dept_array', dept_no_array, 1, 4);    /* Bind only elements 1 through 4 to the cursor Happens 4 times */      dummy := DBMS_SQL.EXECUTE(c);    /* Execute the Query, and return number of rows deleted! */      DBMS_SQL.CLOSE_CURSOR(c);       EXCEPTION WHEN OTHERS THEN      IF DBMS_SQL.IS_OPEN(c) THEN        DBMS_SQL.CLOSE_CURSOR(c);      END IF;      RAISE;  END;  /     P.S. Pure rip-off, with some more commments ,from Oracle

PostgreSQL 服务端绑定变量的用法与之类似

PREPARE,准备DB端绑定变量SQL

EXECUTE,绑定并执行

DEALLOCATE,删除绑定变量

详见:

因此以上Oracle的代码可以改成如下:

do language plpgsql $$  DECLARE    stmt VARCHAR(200);    dept_no_array numeric[];    c numeric;  begin    dept_no_array[1] := 10; dept_no_array[2] := 20; /* Put some values into the array */    dept_no_array[3] := 30; dept_no_array[4] := 40;    dept_no_array[5] := 30; dept_no_array[6] := 40;    execute format('prepare stmt(numeric) as delete from emp where deptno = $1');    /* A Dynamic SQL String with a bind variable */      foreach c in array dept_no_array[1:4]    loop      execute format('execute stmt(%s)', c);   -- 执行绑定SQL    end loop;      DEALLOCATE stmt;      EXCEPTION WHEN OTHERS THEN      DEALLOCATE stmt;      RAISE;  END;  $$;

如果不需要用到绑定变量,那就更简单了。

do language plpgsql $$  DECLARE    dept_no_array numeric[];    c numeric;  begin    dept_no_array[1] := 10; dept_no_array[2] := 20; /* Put some values into the array */    dept_no_array[3] := 30; dept_no_array[4] := 40;    dept_no_array[5] := 30; dept_no_array[6] := 40;      foreach c in array dept_no_array[1:4]    loop      delete from emp where deptno = c;    end loop;      DEALLOCATE stmt;      EXCEPTION WHEN OTHERS THEN      DEALLOCATE stmt;      RAISE;  END;  $$;

例子

建表

do language plpgsql $$declarebegin  execute 'drop table if exists test';  execute 'create table test(id int primary key, info text, crt_time timestamp)';    for i in 0..1023 loop    execute format('drop table if exists test%s', i);    execute format('create table test%s (like test including all)', i);  end loop;end;$$;

使用动态SQL,写入目标子表

create or replace function dyn_pre(int) returns void as $$declare  suffix int := mod($1,1024);begin  execute format('insert into test%s values(%s, md5(random()::text), now()) on conflict(id) do update set info=excluded.info,crt_time=excluded.crt_time', suffix, $1);end;$$ language plpgsql strict;

使用绑定变量,写入目标子表

create or replace function dyn_pre(int) returns void as $$declare  suffix int := mod($1,1024);begin  execute format('execute p%s(%s)', suffix, $1);  exception when others then    execute format('prepare p%s(int) as insert into test%s values($1, md5(random()::text), now()) on conflict(id) do update set info=excluded.info,crt_time=excluded.crt_time', suffix, suffix);    execute format('execute p%s(%s)', suffix, $1);end;$$ language plpgsql strict;

性能对比

vi test.sql\set id random(1,1000000000)select dyn_pre(:id);pgbench -M prepared -n -r -P 1 -f ./test.sql -c 56 -j 56 -T 120

1、使用动态SQL,TPS约5.2万。

2、使用函数内绑定变量,TPS约13.4万。

参考

转载地址:http://kakdl.baihongyu.com/

你可能感兴趣的文章
180626-Spring之借助Redis设计一个简单访问计数器
查看>>
Thread Communication
查看>>
模仿墨迹天气-demo
查看>>
批量修改表引擎
查看>>
mysql基于日志点的复制步骤
查看>>
查看centos中的用户和用户组
查看>>
Elixir ABC 1
查看>>
ZeroSpeech
查看>>
Fiddler 调试手机应用
查看>>
spring 3.2 mvc 点击修改按钮时<form:checkbox/>使原来选中的前面画勾
查看>>
常用的正则表达式
查看>>
Jstl 中<c:if test="${value=='0'}"> 不能做判断??
查看>>
python matplotlib及sklearn安装
查看>>
困惑2017?
查看>>
KOTree
查看>>
BlockAlertsAnd-ActionSheets
查看>>
CA360
查看>>
iOSPlot
查看>>
开源 免费 java CMS - FreeCMS1.4-系统配置
查看>>
开源 java CMS - FreeCMS2.5 标签formTable自定义表单
查看>>