1

试图将一些 pgpl/SQL 迁移到 psql oracle 函数,我发现了一个我根本无法解释的奇怪行为。

这是我的功能:

CREATE OR REPLACE FUNCTION small_distinct(
   tableName IN varchar, 
   cols IN COL_ARRAY,     
   whereCond IN varchar
)
RETURN varchar 
IS
  nbcols PLS_INTEGER;
  currentcolnumber PLS_INTEGER;
  currentcol varchar(100);
  firstcol varchar(100);
  sqlpart varchar(4000);
  firstquery_str VARCHAR2(4000);
  query_str VARCHAR2(4000);
  big_query_str VARCHAR2(10000);
  firstresult varchar(100);
  opt SYS_REFCURSOR;
BEGIN
  firstcol:= cols(1);
  sqlpart := firstcol;
  nbcols := cols.COUNT;
  currentcolnumber :=  2;
  big_query_str := 'SELECT * from ( SELECT '|| sqlpart ||' FROM '||tableName||' WHERE ' ||    whereCond|| ' ORDER BY '|| firstcol || ') WHERE ROWNUM = 1';

  while currentcolnumber <= nbcols loop
     sqlpart := sqlpart || ', ' ||cols(currentcolnumber);
     currentcolnumber := currentcolnumber +1;
  end loop;

  EXECUTE IMMEDIATE 'SELECT * from (SELECT '|| firstcol ||' FROM '||tableName ||' WHERE ' || whereCond|| ' ORDER BY '|| firstcol || ') WHERE ROWNUM = 1 ' INTO firstresult;

  while firstresult is not null 
  loop
    big_query_str := big_query_str || ' UNION ' || 'SELECT * from ( SELECT '|| sqlpart ||' FROM '||tableName||' WHERE '|| firstcol ||' > '''|| firstresult||''' AND ' || whereCond|| ' ORDER BY '|| firstcol || ') WHERE ROWNUM  = 1  ';
    EXECUTE IMMEDIATE 'SELECT * from ( SELECT ' || firstcol ||' FROM '||tableName ||' WHERE '|| firstcol ||' > '''|| firstresult||''' AND '|| whereCond|| ' ORDER BY '|| firstcol || ') WHERE ROWNUM = 1' INTO firstresult;
  end loop;

  return big_query_str;
END small_distinct; 

这个函数编译得很好,但是当函数返回时我的 varcharbig_query_str为空。

正如您在我的函数中看到的那样,这varchar不可能为空,因为我在第 18 行用一个值对其进行了初始化

我试图删除 so 行以发现问题可能是什么,只有当我删除 while 循环(第 24 行附近)时,返回值才不是 null

有人至少向我解释一下什么样的事件可以重置 PL/SQL 中的 varchar ?

4

3 回答 3

1

尝试在 firstresult 行周围添加异常处理程序。

BEGIN EXECUTE IMMEDIATE 'SELECT * from ( SELECT ' || firstcol ||' FROM '||tableName ||' WHERE '|| firstcol ||' > '''|| firstresult||''' AND '|| whereCond|| ' ORDER BY '|| firstcol || ') WHERE ROWNUM = 1' INTO firstresult; EXCEPTION WHEN no_data_found THEN EXIT; END;

在我看来,它会继续到最后一条记录,然后得到一个 no_data_found,因为没有更多记录在“firstcol > firstresult”处。

于 2013-07-22T14:26:39.860 回答
1

尝试将此循环包含在 BEGIN/EXCEPTION/END 中。是否有可能在此循环中发生错误并且return big_query_str未执行?

BEGIN
  while firstresult is not null 
  loop
    big_query_str := big_query_str ||........
    EXECUTE IMMEDIATE....
  end loop;
  return big_query_str;

EXCEPTION
   WHEN OTHERS THEN 
     return 'ERROR';      
END;
于 2013-07-22T13:59:46.437 回答
0

我对此不确定,但您的 big_query_str 被定义为长度为 10,000 的 varchar2。返回 SQL 时 varchar2 的最大允许长度为 4000 个字符。所以,也许,这是一个问题?您可以尝试将 big_query_str 定义为 CLOB 类型,然后从函数中返回它(在对函数进行必要的更改之后)

于 2013-07-22T13:40:10.850 回答