Oracle的PLSQL中动态执行函数
背景
某个PLSQL的函数中,通过 if-elsif 控制执行分支,代码行数巨大,影响更新、编译和维护。
解决方法
希望通过策略模式,依据策略类型,动态执行函数。
注:策略模式,集中定义,遍历执行,与一般的策略模式没有区别,略述。
动态执行方法
方法1:使用动态sql+bind变量
关键点:
- 返回值使用集合类型;
- 返回值用select into ;
- 参数使用bind。
-- 使用动态sql+bind变量-- **[可行1]**/* dbms_output.put_line(chr(10)||'--3、使用动态sql+bind变量');execute immediate 'select ' || vs_fun_name ||'(:I_TABLENAME,:I_WHERESQL ) from dual'into vt_return_result using I_TABLENAME, I_WHERESQL ;dbms_output.put_line('3.1、使用动态sql+bind变量: 执行ok');dbms_output.put_line('executor.vn_result:' || vt_return_result.o_id || ' ' ||vt_return_result.o_msg);*/
方法2:使用动态代码块+bind变量
关键点:
- 动态sql是代码块;
- 使用绑定,支持入参、出参、返回值等3种类型,【扩展性更好】 ;
dbms_output.put_line('5.1、使用动态sql-代码块+bind out 变量');vs_sql_execute := 'begin' || ' :result:=' || vs_fun_name ||'(:input1,:input2,:msg); ' || 'end;';execute immediate vs_sql_executeusing out vn_result, in I_TABLENAME, in I_WHERESQL, out vs_RETURN_MSG;dbms_output.put_line('5.2、使用动态sql-代码块+bind out 变量: ok');dbms_output.put_line('executor.vn_result:' || vn_result || ' ' ||vs_RETURN_MSG);
不可行的方法
法1:出参函数无法直接调用
直接使用出参变量名【O_RETURN_MSG】,无法识别变量
vs_sql_execute := 'declare O_RETURN_MSG varchar2(30000); vn_result number := 0;begin vn_result := ';vs_sql_execute := vs_sql_execute || vs_fun_name;vs_sql_execute := vs_sql_execute || '(''' || ''',' || I_WHERESQL || ',' ||'O_RETURN_MSG); dbms_output.put_line(''executor.O_RETURN_MSG:'' || O_RETURN_MSG);' ||'dbms_output.put_line(''executor.vn_result:'' || vn_result);end;';execute immediate vs_sql_execute */--vs_sql_execute:='select '||vs_fun_name||'('''||I_TABLENAME||''','''||I_WHERESQL||''','||'O_RETURN_MSG) from dual';-- 使用execute immediate -- **[直接使用变量名,无法识别变量]
法2:使用动态sql+bind out 变量
注意:sql中无法绑定out变量。
-- 使用动态sql+bind out 变量 /* dbms_output.put_line(chr(10) || '--4、使用动态sql+bind out 变量 ');execute immediate 'select ' || vs_fun_name ||'(:I_TABLENAME,:I_WHERESQL,:out_msg ) from dual'--into vn_resultusing I_TABLENAME, I_WHERESQL,out vs_RETURN_MSG;dbms_output.put_line('4.1、使用动态sql+bind out 变量: 执行ok');dbms_output.put_line('executor.vn_result:' || vn_result || ' ' ||vs_RETURN_MSG);*/