`
z_kanhai
  • 浏览: 49170 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

以字符串数组为输入参数的存储过程

阅读更多
今天项目中需要用到存储过程,使用的是字符串数组作为参数,经过不断尝试,终于搞定了
下面简单的记录下:

1、创建自定义数据类型
--自定义数据类型(可做数组用)
create or replace type jqjk_array AS VARRAY(50) of varchar(50); 


2、创建遍历数组循环的存储过程
CREATE OR REPLACE PROCEDURE testvarray(s_table  in jqjk_array,
                                       t_table  in jqjk_array,
                                       pk_field in jqjk_array,
                                       dd       out varchar) IS
  s_tableValue  varchar2(50);
  t_tableValue  varchar2(50);
  pk_fieldValue varchar2(50);
BEGIN
  dd := 'success';
  for i in 1 .. s_table.count LOOP
    BEGIN
      s_tableValue  := s_table(i);
      t_tableValue  := t_table(i);
      pk_fieldValue := pk_field(i);
      if s_tableValue is null or t_tableValue is null or
         pk_fieldValue is null then
        dd := '存在为空的值 ';
        exit;
      else
      --调用另外一个存储过程,传入参数
        pro_data_synchronic(s_tableValue, t_tableValue, pk_fieldValue);
      end if;
            EXCEPTION WHEN dup_val_on_index 
        THEN dd := 'error ';
        exit;
      end;
    
  end LOOP;
END testvarray;

这是上一个过程中调用的存储过程,用于同步两张结构一样的表的数据
create or replace procedure pro_data_synchronic (s_table nvarchar2, t_table nvarchar2, pk_field nvarchar2)
as 
   step_one_sql varchar2(2000);
   step_two_sql varchar2(2000);
   step_three_sql varchar2(2000);
   delete_sql varchar2(200);
   s_pk_field varchar2(50);
   t_pk_field varchar2(50);
   s_ts varchar2(50);
   t_ts varchar2(50);
begin 
   /**
   * 数据同步主要分为三步:
   * 第一步:先删除目标表中存在的,但是来源表中不存在的数据(主要处理来源表物理删除的数据)
   * delete from jq_bd_bdinfo where pk_bdinfo not in (select pk_bdinfo from bd_bdinfo);
   *
   * 第二步:删除已同步给目标表,但数据在源表中做过更新的数据
   * delete from jq_bd_bdinfo where pk_bdinfo in 
   *         (select  bd_bdinfo.pk_bdinfo from bd_bdinfo
   *                    inner join jq_bd_bdinfo on bd_bdinfo.pk_bdinfo=jq_bd_bdinfo.pk_bdinfo and bd_bdinfo.ts != jq_bd_bdinfo.ts);
   *
   * 第三步:同步源表中存在但目标表中不存在的数据给目标表
   * insert into jq_bd_bdinfo select * from bd_bdinfo where bd_bdinfo.pk_bdinfo not in (select pk_bdinfo from jq_bd_bdinfo);
   **/
   
   s_pk_field := s_table || '.' || pk_field;
   s_ts := s_table || '.' ||'ts';
   t_pk_field := t_table || '.' || pk_field;
   t_ts := t_table || '.' ||'ts';
   
   delete_sql := 'delete from ' || t_table || ' where '|| pk_field;
   
   step_one_sql := delete_sql || ' not in (select ' || pk_field || ' from ' || s_table || ')';
   
   DBMS_OUTPUT.PUT_LINE(step_one_sql);
   
   step_two_sql := delete_sql || ' in (' || ' select ' || t_pk_field || ' from ' || t_table;
   step_two_sql := step_two_sql || ' inner join ' || s_table || ' on ' || s_pk_field || '=' || t_pk_field;
   step_two_sql := step_two_sql || ' and ' || s_ts || '!=' || t_ts;
   step_two_sql := step_two_sql || ' )';
   
   DBMS_OUTPUT.PUT_LINE(step_two_sql);
   
   step_three_sql := 'insert into ' || t_table || ' select * from ' || s_table || ' where ' || s_pk_field;
   step_three_sql := step_three_sql || ' not in ( select ' || t_pk_field || ' from ' || t_table || ')';
   
   DBMS_OUTPUT.PUT_LINE(step_three_sql);
   
   execute immediate step_one_sql;
   
   execute immediate step_two_sql;
   
   execute immediate step_three_sql;
   
   commit;
   
end;


3、下面看下java代码中是如何调用的
public void testArrayProceduer() {
		String[] t_table = { "jq_CORP",
				"jq_BDINFO",
				"jq_CURRTYPE",
				"jq_PSNDOC",
				"jq_DEPTDOC",
				"jq_CUBASDOC",
				"jq_CASHFLOW",
				"jq_JOBBASFIL",
				"jq_GLORG",
				"jq_GLORGBOOK",
				"jq_ACCSUBJ",
				"jq_VOUCHER",
				"jq_DETAIL",
				"jq_FREEVALUE",
				"jq_BALANCE",
				"jq_VERIFYDETAIL",
				"jq_GLBOOK",
				"jq_JobMngFil",
				"jq_cashflowcase",
				"jq_vouchertype",
				"jq_user" };
		String[] s_table = { "bd_corp", "BD_BDINFO", "BD_CURRTYPE","BD_PSNDOC" , 
				"BD_DEPTDOC", "BD_CUBASDOC", "BD_CASHFLOW",
				"BD_JOBBASFIL", "BD_GLORG", "BD_GLORGBOOK", "BD_ACCSUBJ",
				"GL_VOUCHER", "GL_DETAIL", "GL_FREEVALUE", "GL_BALANCE",
				"GL_VERIFYDETAIL", "BD_GLBOOK", "bd_JobMngFil","GL_CASHFLOWCASE",
				"BD_VOUCHERTYPE", "SM_USER" };
		String[] pk_field = { "pk_corp", "pk_bdinfo", "pk_currtype","pk_psndoc" ,
				"pk_deptdoc", "pk_cubasdoc", "pk_cashflow",
				"pk_jobbasfil", "pk_glorg", "pk_glorgbook", "pk_accsubj",
				"pk_voucher", "pk_detail", "pk_freevalue", "pk_balance",
				"pk_verifydetail", "pk_glbook", "pk_jobmngfil","pk_cashflowcase",
				"pk_vouchertype", "cuserid" };
		ResultSet rs = null;
		ArrayDescriptor arrDesc = null;
		CallableStatement proc = null;
		try {
			 			proc = getConn().prepareCall(
					"{ call cs_20120208.testvarray(?,?,?,?) }");
			arrDesc = ArrayDescriptor.createDescriptor("JQJK_ARRAY", getConn()); // jqjk_array
			 /*重要!如果遇到在存储过程中获取不到参数或者获取到的参数值为null时, 请检查有没有加载该类库orai18n.jar(11g之前:nls_charset12.jar)*/
			 			ARRAY array1 = new ARRAY(arrDesc, getConn(), s_table);
			ARRAY array2 = new ARRAY(arrDesc, getConn(), t_table);
			ARRAY array3 = new ARRAY(arrDesc, getConn(), pk_field);
			proc.setArray(1, array1);
			proc.setArray(2, array2);
			proc.setArray(3, array3);
			proc.registerOutParameter(4, Types.VARCHAR);
			proc.execute();

			String ss = (String) proc.getObject(4);
			System.out.println(" 返回结果: " + ss);
		} catch (SQLException ex2) {
			ex2.printStackTrace();
		} catch (Exception ex2) {
			ex2.printStackTrace();
		} finally {
			try {
				closeConn();
				if (rs != null) {
					rs.close();
					if (proc != null) {
						proc.close();
					}
				}
			} catch (SQLException ex1) {
			}
		}
	}


这种情况也可以通过下面两种方式实现:
1、将数组改为一个用逗号连接的字符串,到存储过程中进行拆分;
2、将需要传入的数组放入一个表中,在存储过程中使用游标遍历
如:
CREATE OR REPLACE PROCEDURE optjqr(rs out varchar) IS
  s_tableValue  varchar2(50);
  t_tableValue  varchar2(50);
  pk_fieldValue varchar2(50);
  CURSOR  CUR_TEMP is
    select s_table, t_table, pk_field from jq_param ORDER BY nm;
BEGIN
  rs := 'success';
  open CUR_TEMP;
  LOOP
     --把游标的某行值赋值给变量
    fetch CUR_TEMP
      into s_tableValue, t_tableValue, pk_fieldValue;
      --调用存储过程
      pro_data_synchronic(s_tableValue, t_tableValue, pk_fieldValue);     
      --无数据时退出
    EXIT WHEN CUR_TEMP%NOTFOUND;
  end LOOP;
  --关闭游标
  if CUR_TEMP%isopen then
    close CUR_TEMP;
  end if;
END optjqr;
分享到:
评论

相关推荐

    C语言编写的统计字符出现次数.pdf

    在`main`函数中,我们定义了一个字符串数组`str`和一个字符变量`ch`,用于存储输入的字符串和要统计的字符。然后,使用`scanf`函数从用户输入中读取字符串和字符。注意在读取字符时,我们在格式字符串中使用了空格,...

    串的基本操作.cpp

    (e)过程中记录替换字符串的次数,遍历结束后返回该次数(如果没有替换则为0); 如果有必要,可以使用本实验已经提供的相关函数,如:求子串位置的函数MySubStrIndex(),子串删除函数MyStrDelete()和子串插入函数...

    C语言程序设计标准教程

     本程序中用赋值语句给num和name两个成员赋值,name是一个字符串指针变量。用scanf函数动态地输入sex和score成员值,然后把boy1的所有成员的值整体赋予boy2。最后分别输出boy2 的各个成员值。本例表示了结构变量的...

    明解C语言(第3版)入门篇.[日]柴田望洋(带详细书签).pdf 【半高清】

    字符串数组的参数传递 280 总结 283 第10章 指针 285 10-1 指针 286 函数的参数 286 对象和地址 287 取址运算符 288 指针 289 指针运算符 291 10-2 指针和函数 293 作为函数参数的指针 293 计算和与差 ...

    javascript入门笔记

    Javascript Basic 1、Javascript 概述(了解) ... 调用函数时,所传递的参数列表,称之为"实参(实际参数)" 3、练习 1、定义一个函数 change ,该函数中接收两个参数(a,b) 2、在函数体中,如果 a 大于 b的话...

    VBSCRIPT中文手册

    Filter 函数 根据指定的筛选条件,返回含有字符串数组子集的、下限为 0 的数组。 FirstIndex 属性 返回字符串匹配的位置。 Fix 函数 返回数的整数部分。 For...Next 语句 以指定的次数重复一组语句。 For Each......

    vb Script参考文档

    Filter 函数 根据指定的筛选条件,返回含有字符串数组子集的、下限为 0 的数组。 FirstIndex 属性 返回字符串匹配的位置。 Fix 函数 返回数的整数部分。 For...Next 语句 以指定的次数重复一组语句。 For Each......

    VBScript 语言参考

    Filter 函数 根据指定的筛选条件,返回含有字符串数组子集的、下限为 0 的数组。 FirstIndex 属性 返回字符串匹配的位置。 Fix 函数 返回数的整数部分。 For...Next 语句 以指定的次数重复一组语句。 For Each......

    VBScript 语言参考中文手册CHM

    Filter 函数 根据指定的筛选条件,返回含有字符串数组子集的、下限为 0 的数组。 FirstIndex 属性 返回字符串匹配的位置。 Fix 函数 返回数的整数部分。 For...Next 语句 以指定的次数重复一组语句。 For Each......

    VBSCRIP5 -ASP用法详解

    Filter 函数 根据指定的筛选条件,返回含有字符串数组子集的、下限为 0 的数组。 FirstIndex 属性 返回字符串匹配的位置。 Fix 函数 返回数的整数部分。 For...Next 语句 以指定的次数重复一组语句。 For Each......

    C语言程序设计(谭浩强)第三版

     6.3.4字符串和字符串结束标志  6.3.5字符数组的输入输出  6.3.6使用字符串处理函数  6.3.7字符数组应用举例  习题 第7章:用函数实现模块化程序设计 7.1为什么要用函数  7.2怎样定义函数  7.2.1为什么要定义...

    C程序设计(第四版)学习辅导【谭浩强】

    6.3.4字符串和字符串结束标志157 6.3.5字符数组的输入输出160 6.3.6使用字符串处理函数162 6.3.7字符数组应用举例166 习题169 第7章用函数实现模块化程序设计171 7.1为什么要用函数171 7.2怎样定义函数173 7.2.1为...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    5.6.3 字符串数组 5.6.4 字符串运算举例 习题 第6章 指针 6.1 指针的概念 6.2 变量与指针 6.2.1 定义指针变量 6.2.2 引用指针变量 6.2.3 指针作为函数参数 6.3 数组与指针 6.3.1 指向数组元素的指针 6.3.2 用指针...

    C语言讲义.doc

    2.2 通过指针访问字符串数组 64 2.3 函数的参数为CHAR * 64 2.4 指针数组做为MAIN函数的形参 65 3 内存管理 65 3.1 作用域 65 3.1.1 auto自动变量 65 3.1.2 register寄存器变量 65 3.1.3 代码块作用域的静态变量 66 ...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    5.6.3 字符串数组 5.6.4 字符串运算举例 习题 第6章 指针 6.1 指针的概念 6.2 变量与指针 6.2.1 定义指针变量 6.2.2 引用指针变量 6.2.3 指针作为函数参数 6.3 数组与指针 6.3.1 指向数组元素的指针 6.3.2 用指针...

    谭浩强C程序设计第三版

    使用字符串指针变量与字符数组的区别 168 函数指针变量 169 指针型函数 170 指针数组和指向指针的指针 171 指针数组的概念 171 指向指针的指针 174 main函数的参数 176 有关指针的数据类型和指针运算的小结 177 有关...

    c程序设计习题参考(谭浩强三版)习题参考解答

    8.8编写一函数,有实参传来一个字符串,统计此字符串中字母,数字,空格和其它字符的个数,在主函数中输入字符串以及输出上述的结果。 52 8.10写一函数,用“起泡法”对输入的10个字符按由小到大的顺序排列。 54 ...

    c# 加密和解密相关代码

    如果此字符串是空字符串,则返回的数组为空且 长度为零。 (2)Convert 类的ToChar 方法 Convert 类的ToChar 方法用来将指定的值转换为Unicode 字符,该方法为可重载方法,本实例中用到的它 的重载形式如下: public...

Global site tag (gtag.js) - Google Analytics