动态 SQL 接受表列作为过程中的输入

Posted

技术标签:

【中文标题】动态 SQL 接受表列作为过程中的输入【英文标题】:Dynamic SQL accept table column as input in a procedure 【发布时间】:2013-02-06 17:17:45 【问题描述】:

嘿,我正在尝试编写一个程序,用户可以在其中insert 他想以parameter input 获得哪些列。截至目前,当我运行测试 script 时,我收到此错误:

error -1 message error in ct_cu_act_medrecon_pg.spm_search_patientmedrecs =>ORA-00933: SQL command not properly ended

错误是指select statement 中的order by 部分,当我删除它时,我收到一条错误消息:

error -1 message error in ct_cu_act_medrecon_pg.spm_search_patientmedrecs =>ORA-00904: "D"."P_INSERTDT_IN": invalid identifier

这是规格:

procedure spm_search_patientmedrecs (
  p_columnsort_in  in varchar2, --which is sort column
  p_medmed_in      in varchar2, --first column
  p_planid_in      in varchar2, --second column
  p_detmed_in      in varchar2, --third column
  p_insertdt_in    in varchar2, --fourth column
  p_ascdesc_in     in varchar2, --asc or desc in order by
  p_return_cur_out out sys_refcursor,
  p_err_code_out   out number,
  p_err_mesg_out   out varchar2
);

这是程序主体:

procedure spm_search_patientmedrecs (
  p_columnsort_in  in varchar2,
  p_medmed_in      in varchar2,
  p_planid_in      in varchar2,
  p_detmed_in      in varchar2,
  p_insertdt_in    in varchar2,
  p_ascdesc_in     in varchar2,
  p_return_cur_out out sys_refcursor,
  p_err_code_out   out number,
  p_err_mesg_out   out varchar2)
is
  lv_sql           varchar2(32767);
begin
  lv_sql := '';
  lv_sql := 'select h.p_medmed_in,
                    h.p_planid_in,
                    d.p_detmed_in,
                    d.p_insertdt_in
             from membermedicalreconcilationhdr h,
                  membermedicalreconcilationdet d
             where h.membermedreconciliationhdrskey = 
                   d.membermedreconciliationhdrskey
             order by h.p_columnsort_in p_ascdesc_in';
    p_err_code_out := 0;
    OPEN p_return_cur_out FOR lv_sql;
exception
  when others then
    p_err_code_out := -1;
    p_err_mesg_out := 'error in ct_cu_act_medrecon_pg.spm_search_patientmedrecs =>'||sqlerrm;
end spm_search_patientmedrecs;

这是我的测试脚本:

set serveroutput on
declare 
  type tempcursor is ref cursor;
  v_cur_result tempcursor;
  errcode number;
  errmesg varchar2(1000);
begin
  ct_cu_act_medrecon_pg.spm_search_patientmedrecs
    ('primarymemberplanid',
     'membermedreconciliationhdrskey',
     'primarymemberplanid',
     'membermedreconciliationdetskey',
     'inserteddt',
     'ASC',
     v_cur_result,
     errcode,
     errmesg
     );

--  dbms_output.put_line(v_cur_result);
  dbms_output.put_line('error '||errcode||' message '||errmesg);
end;

首先,我知道我如何处理错误并不是最好的方法,但这就是要求我这样做的人想要的方式。

现在我不知道这是否可能在Oracle PL/SQL 中做,但如果是的话,我将非常感谢一些帮助,为我指明正确的方向。如果你们需要更多信息,请随时询问,我会尽我所能提供帮助(我只使用 SQL 和 PL/SQL 2 个月)。提前致谢。

【问题讨论】:

【参考方案1】:

动态 SQL 是指将作为 SQL 语句执行的字符串组合起来。您的字符串硬编码参数名称,而您真正需要的是参数的内容。

类似这样的:

lv_sql := 'select h.'||p_medmed_in||',
                    h.'||p_planid_in||',
                    d.'||p_detmed_in||',
                    d.'||p_insertdt_in||'
             from membermedicalreconcilationhdr h,
                  membermedicalreconcilationdet d
             where h.membermedreconciliationhdrskey = 
                   d.membermedreconciliationhdrskey
             order by h.'||p_columnsort_in||' '|| p_ascdesc_in;

【讨论】:

啊有趣,让我看看这个,看看它是怎么回事。感谢您的及时回复并为我清理动态sql。 @Alex - 好吧,我确实说过“类似这样的东西” :) 感谢您在我之后收拾东西!

以上是关于动态 SQL 接受表列作为过程中的输入的主要内容,如果未能解决你的问题,请参考以下文章

创建接受输入作为存储过程并动态产生结果的存储过程

SQL 动态数据透视表列顺序

如何使用 pl sql 过程从结构仅在运行时知道的 oracle 表中动态获取数据?

动态创建元素

在动态 SQL 的“IN”子句中使用 CSV 字符串值

当使用 sp_executesql 作为过滤器时,保护 t-sql 动态代码的最佳方法是啥