DB2存储过程——prepare
prepare:标识动态sql的
因为1.用变量做表名: 简单的用set或者declare语句定义变量,然后直接作为sql的表名是不行的,mysql会把变量名当作表名。在其他的sql数据库中也是如 此,mssql的解决方法是将整条sql语句作为变量,其中穿插变量作为表名,然后用sp_executesql调用该语句。仅对procedure有 效,function不支持动态查询
最近job调度平台的项目要核对数据,需要编写一个存储过程来获取生产库上相关表的总记录条数,
通过与测试库上的数据条数进行对比来进行大致的核对。由于我之前没写过DB2的过程,所以写起来
比较费劲,不过最终还是完成了。
具体是这样的:我们先通过SQL在生产上查找出与项目相关的表,在存储过程中声明一个临时表来
存放这些表名,并用另一个字段来存储各表的记录条数;
然后,声明一个游标来获取所有的表名(这里游标不要从临时表里来获取数据,在临时表声明前就
要声明游标,游标数据同临时表一样通过SQL来获取);
接着就是通过游标来生成动态的SQL。在DB2中动态SQL中包含SELECT或者VALUES是不能够直接执行
的,这也是一直困扰我的地方。在网上看了好多相关的资料,经过多次尝试,最终找到了解决办法。
要执行包含SELECT或者VALUES的动态SQL 语句,要做以下几步:
1.声明一个存放动态SQL的变量 v_sql
2.声明一个statement类型的变量 v_stmt
3.为statement变量声明一个游标 c2
4.写好动态SQL语句 set v_sql='select count(*) from dbo.'||v_1;--(v_1为表名)
5.prepare v_stmt from v_sql
6.打开游标c2,fetch c2 into v_count; 关闭游标
最后用v_count的值来更新临时表,进行数据导出;
call sysproc.admin_cmd('export to /home/db2inst1/validate/validate.csv of del select * from session.tmp');
导出数据时,我想直接导出到本地,刚一开始就写了个本地的路径,结果报错了,后来才知道要一个远程服务器
的路径才可以,并且用户要有写入的权限。
declare v_sql varchar(4000) default '';--动态sql 可以看到这里是声明了一个变量,字符串,默认值是空字符串 --程序开始 --表-- if upper(v_lx) = 'T' then if exists(select 1 from sysibm.tables where table_schema = 'PAS' and table_name= ltrim(rtrim(replace(upper(v_ccmc),'PAS.','')))) then set v_sql='drop table '||v_ccmc; prepare s1 from v_sql; 而在这里声明了这个变量是一个动态sql,然后就去执行了,不如不声明的话就有可能会出现把变量本身作为参数了 execute s1; end if; end if;
PS:说下我个人的大白话理解
动态sql:
假设我们声明两个个变量 declare v_sql varchar(4000) default '';(动态sql语句,默认值为空字符串),declare v_cmcc varchar(40);(传进来的值为jxdx_ckzh)
,给变量赋值set v_sql='drop table'||v_ccmc
那么我们用execute去执行这条sql 执行的语句就是 drop table jxdx_ckzh
不声明为动态sql的话:
直接用execute去执行v_sql :excute v_sql
执行的就是 drop table v_cmcc 删除的就是这个表