以字符串数组为输入参数的存储过程
程序员文章站
2022-06-04 07:56:54
...
今天项目中需要用到存储过程,使用的是字符串数组作为参数,经过不断尝试,终于搞定了
下面简单的记录下:
1、创建自定义数据类型
--自定义数据类型(可做数组用)
2、创建遍历数组循环的存储过程
这是上一个过程中调用的存储过程,用于同步两张结构一样的表的数据
3、下面看下java代码中是如何调用的
这种情况也可以通过下面两种方式实现:
1、将数组改为一个用逗号连接的字符串,到存储过程中进行拆分;
2、将需要传入的数组放入一个表中,在存储过程中使用游标遍历
如:
下面简单的记录下:
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;
推荐阅读
-
Mysql通过存储过程分割字符串为数组
-
使用动态SQL处理table_name作为输入参数的存储过程(MySQL)
-
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
-
5位评委对参赛选手进行打分,将所有的打分结果存储到对应类型的数组中, 将所有的评分结果去除一个最低分,去除一个最高分,然后获取的平均分数为 选手的最终得分.设计程序,用键盘输入5位评委的评分,并打印输
-
java 中文字符串,utf-8编码为byte数组的计算过程
-
存储过程为参数NULL时的处理方法
-
创建一个存储过程,以部门号为参数,查询该部门的平均工资,并输出该部门中比平均工资高的员工号、员工名。并且调用该存储过程,要求根据输入部门编号,查询平均工资及输出比平均工资高的员工号、员工名
-
在Python中输入一个以空格为间隔的数组方法
-
在调用存储过程输出参数时输出参数的值老是为null
-
MDaemon以MySQL为存储方式的配置过程