首页 > 技术文章 > DB2存储过程——prepare

wy20110919 2018-05-17 15:11 原文

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 删除的就是这个表

 

推荐阅读