存储过程问题:
在线等,很难,答出来立即给分。
现在要求是传入一个查询SQL语句,返回这个SQL语句的结果。
前提:SQL语句查询的项目数根据SQL语句不同而不同。SQL语句中可能有函数,子查询等等。非常复杂。SQL查询出来的数据,要一项一项的检查,发现前两个字符等于“DD”就把这项的值变成“SSS”.
把改变后的结果集用 sys_refcursor 传出来。我已经想到一部分,但是做不下去了。请大家多多帮忙,解决立即给分,高手们加油阿:function fun_test(in_sql in varchar2, out_refcur out ref_cur) return number is
    v_sql       varchar2(400);
    v_CursorID  integer;
    v_Dummy     INTEGER;
    v_ReturnRow INTEGER;
    l_columnValue    VARCHAR2(4000);
    v_errmsg    varchar2(20);
    l_descTbl       dbms_sql.desc_tab;
    l_colCnt        number;  begin
    v_sql      := in_sql;
    v_CursorID := DBMS_SQL.OPEN_CURSOR;
    DBMS_SQL.PARSE(v_CursorID, v_sql, DBMS_SQL.native);
    dbms_sql.describe_columns( v_CursorID, l_colCnt, l_descTbl );
    
    
    for i in 1 .. l_colCnt loop
        dbms_sql.define_column(v_CursorID, i, l_columnValue, 4000);
    end loop;    v_Dummy := DBMS_SQL.EXECUTE(v_CursorID);
    
    loop
      v_ReturnRow := DBMS_SQL.FETCH_ROWS(v_CursorID);
      if v_ReturnRow = 0 then
        exit;
      end if;
      for i in 1 .. l_colCnt loop
        DBMS_SQL.COLUMN_VALUE(v_CursorID, i, l_columnValue);
        if not l_columnValue is null then 
          if length(l_columnValue) > 2 and substr(l_columnValue,1,2) = 'DD' then
            l_columnValue := 'SSS';
          end if;
        end if;
      end loop; 
    end loop;
  
    DBMS_SQL.CLOSE_CURSOR(v_CursorID);
  
--    open out_refcur for v_sql;  exception 
    when others then
      v_errmsg := sqlerrm;  end;

解决方案 »

  1.   

    人多数下班了,等明天吧!
    感觉你写的好的很啊!哪有问题?顺便问下:
    DBMS_SQL.PARSE这些东西是什么意思,没用过啊!
      

  2.   

    我写的是一半的程序,实现了
    SQL查询出来的数据,要一项一项的检查,发现前两个字符等于“DD”就把这项的值变成“SSS”. 
    但是,这个结果集我没有办法传出来。
    我编不下去了,不知道又没有高手能够帮我把结果集传出来。
    要不用别的办法实现也可以。最好考虑性能。传入的查询SQL可能1万多字节。注:
     ORACLE 程序包 dbms_sql   
     1、OPEN_CURSOR:返回新游标的ID值 
     2、PARSE:解析要执行的语句 
     3、BIND_VARIABLE:将给定的数量与特定的变量相连接 
     4、DEFINE_COLOUMN:定义字段变量,其值对应于指定游标中某个位置元素的值 
                        (仅用于SELECT语句) 
     5、EXECUTE:执行指定的游标 
     6、EXECUTE_AND_FETCH:执行指定的游标并取记录 
     7、FETCH_ROWS:从指定的游标中取出记录 
     8、COLUMN_VALUE:返回游标中指定位置的元素 
     9、IS_OPEN:当指定的游标状态为OPEN时返回真值 
    10、CLOSE_CURSOR:关闭指定的游标并释放内存 
    11、LAST_ERROR_POSITION:返回出错SQL语句的字节偏移量 
    12、LAST_ROW_ID:返回最后一条记录的ROWID 
    13、LAST_SQL_FUNCTION_CODE:返回语句的SQL FUNCTION CODE
      

  3.   

    关于你这个问题,你可以简单的修改一下就可以实现了的,没有必要搞的这么复杂。
    为了编程的方面,所有的传入的sql 都可以这样些 
    select coli  as FirstCol  .. from ...
    总之,你总是可以些成类似这样的
    然后再在外面套一层
      select case when substr(FirstCol,1,2)='DD' THEN 'SSSS'
                  ELSE Firstcol from ( ....)
      如果你希望在sys_refcursor中返回,那么就把这个语句放在里面,或者不需要procedure,直接在别处处理即可。.还有一种办法可以获得你的查询的第一个字段的名称,通过这个你可以修改你的sql,并结合动态sql来完成。
    declare
      vFirstCol varchar2(32);
    begin
      vFirstCol:=GetFirstcolByQuery(sql);
      --用前面提到的来返回需要的结果。
    end;
      

  4.   

    回答楼上的
    前提:SQL语句查询的项目数根据SQL语句不同而不同。SQL语句中可能有函数,子查询等等。非常复杂。 
    一条一般的SQL语句就是1~2万个字节以上,而且已知条件只有SQL,具体SQL是动态变化的,项目数也是变化的。
    但是需要遍历查询结果的每一个值,要把查询出来的符合条件的值,作为字段名,查询另外一个表取值。我已经用临时表作实现了。看来是没有更好的办法了。结贴!