Oracle/PLSQL 中的分页错误

Posted

技术标签:

【中文标题】Oracle/PLSQL 中的分页错误【英文标题】:Pagination in Oracle/PLSQL error 【发布时间】:2013-02-08 20:17:30 【问题描述】:

嘿,我正在尝试将paging 添加到我在 PLSQL 中的动态 sql 块中,但由于某种原因,当我运行测试脚本时它会出错:

ORA-00932: inconsistent datatypes: expected - got -

这是我的程序:

create or replace 
  procedure spm_search_patientmedrecs (
    p_columnsort_in       in varchar2,
    p_column1_in          in varchar2,
    p_column2_in          in varchar2,
    p_column3_in          in varchar2,
    p_column4_in          in varchar2,
    p_ascdesc_in          in varchar2,
    p_return_cur_out      out sys_refcursor
  is
    lv_sql             varchar2(32767);
    lv_startnum        number:= 1;
    lv_incrementby     number:= 20;
  begin
    lv_sql := '';    
        lv_sql := 'select * from (
                   select /*+ first_rows(20) */
                      '||p_column1_in||',
                      '||p_column2_in||',
                      '||p_column3_in||',
                      '||p_column4_in||',
                      row_number() over
                        (order by '||p_columnsort_in||' '||p_ascdesc_in||') rn
                   from membermedicalreconcilationhdr h,
                        membermedicalreconcilationdet d
                   where h.membermedreconciliationhdrskey = 
                         d.membermedreconciliationhdrskey)
                   where rn between :lv_startnum and :lv_incrementby
                   order by rn';

        open p_return_cur_out for lv_sql;
  end spm_search_patientmedrecs;

这是我的测试脚本:

  set serveroutput on
  declare 
    type tempcursor is ref cursor;
    v_cur_result tempcursor;
    p_columnsort_in   varchar2(50);
    p_column1_in      varchar2(50);
    p_column2_in      varchar2(50);
    p_column3_in      varchar2(50);
    p_column4_in      varchar2(50);
    p_ascdesc_in          varchar2(50);
  begin
    spm_search_patientmedrecs
    ('h.PRIMARYMEMBERPLANID',
     'h.PRIMARYMEMBERPLANID',
     'h.ASSIGNEDUSERID',
     'd.MEMBERMEDRECONCILIATIONDETSKEY',
     'd.GENERICNM',
     'ASC',
     v_cur_result
     );
   loop
      fetch v_cur_result into
        p_column1_in,p_column2_in,p_column3_in,p_column4_in;
        dbms_output.put_line('column 1: '||p_column1_in||' column 2: '||p_column2_in||
                             ' column 3: '||p_column3_in||' column 4: '||p_column4_in);
      exit when v_cur_result%notfound;
    end loop;
  end;

我上面发布的错误对我来说没有意义,但我一直在寻找原因。如果有人能指出我正确的方向,将不胜感激,在此先感谢。

【问题讨论】:

您引用的错误是 ORA-00932 的规范形式;通常我希望- 被预期和得到的实际字符替换。很遗憾,该信息已丢失。 【参考方案1】:

我突然想到了几个问题。

用于返回游标的查询返回 5 列(传入的 4 列加上计算得到的 rn),而 fetch 仅将数据提取到 4 个变量中。您要么需要修改查询以仅返回 4 列,要么修改测试脚本以将数据提取到 5 个变量中。 在您的过程中,您的 SQL 语句中有绑定变量,但您在打开游标时没有传入任何绑定变量。我猜你想要这样的东西

使用USING 子句传递绑定变量

open p_return_cur_out 
     for lv_sql 
   using lv_startnum, lv_incrementby;

可能还有更多错误——如果有,发布完整的堆栈跟踪(包括错误的行号)会很有帮助。

还有一些需要注意的事项。

除非p_columnsort_in 碰巧指定了唯一的列,否则您的分页代码很可能会丢失行和/或在多页中显示行,因为没有完全指定排序顺序。如果第 20 行和第 21 行具有相同的 p_columnsort_in 值,则在第一个查询中以一种方式对它们进行排序并在第二个查询中以另一种方式对它们进行排序是完全合法的,因此第 20 行可能会出现在第一页和第二页上,而第 21 行可能会出现不会出现在任何地方。 如果考虑到效率,使用rownum 最终可能会比使用这样的分析函数更有效,因为优化器通常可以更好地优化rownum 谓词。

【讨论】:

谢谢,看来是 fetch 导致了错误。我从来没有想过我需要添加它。【参考方案2】:
create or replace 
  procedure spm_search_patientmedrecs (
    p_columnsort_in       in varchar2,
    p_column1_in          in varchar2,
    p_column2_in          in varchar2,
    p_column3_in          in varchar2,
    p_column4_in          in varchar2,
    p_ascdesc_in          in varchar2,
    p_return_cur_out      out sys_refcursor
  is
    lv_sql             varchar2(32767);
    lv_startnum        number:= 1;
    lv_incrementby     number:= 20;
  begin
        lv_sql := 'select * from (
                   select /*+ first_rows(20) */
                      '||p_column1_in||',
                      '||p_column2_in||',
                      '||p_column3_in||',
                      '||p_column4_in||',
                      row_number() over
                        (order by '||p_columnsort_in||' '||p_ascdesc_in||') rn
                   from membermedicalreconcilationhdr h,
                        membermedicalreconcilationdet d
                   where h.membermedreconciliationhdrskey = 
                         d.membermedreconciliationhdrskey)
                   where rn between :1 and :2
                   order by rn';
        open p_return_cur_out for lv_sql using lv_startnum, lv_incrementby;
  end spm_search_patientmedrecs;

【讨论】:

以上是关于Oracle/PLSQL 中的分页错误的主要内容,如果未能解决你的问题,请参考以下文章

Oracle PLSQL 无效游标错误我不明白

Oracle中的分页代码

oracle plsql 存储过程错误处理 oracle-6502

Oracle plsql 错误

oracle的分页查询

急! 换电脑之前PLSQL可以正常登陆 换电脑后PLSQL和 ORACLE 都没重装 现在运行plsql登录错误,有空白提示框