lv_sql := 'UPDATE tabledetail
                   SET isdel = '||pi_Flag||'
                   WHERE fileid IN (' ||
                   pi_FileID || ')';
EXECUTE IMMEDIATE lv_sql;存储过程中间的这一段包括了IN。怎么才能改成不用IN的形式?
1.用WHILE .... LOOP 的方式把pi_FileID按“,”拆开,每循环一次都要执行一次UPDATE。
2.用循环把pi_FileID拆开放到虚拟表里面。然后UPDATE的时候直接从虚拟表找出来,执行一次?
具体应该怎么做啊?
请各位大侠帮帮忙!我不会写。

解决方案 »

  1.   

    不太懂呀
    从虚拟表找出来后,不还得写成 fileid IN (select column_value from table(..))
    这样的?
    绕了一个圈,为点啥
      

  2.   

    其实上头的意思主要是防SQL注入,我的那种写法不安全。
      

  3.   

    建议使用 2.用循环把pi_FileID拆开放到虚拟表里面。然后UPDATE的时候直接从虚拟表找出来,执行一次
    然后用绑定变量的方式执行
      

  4.   

    如果 tabledetail 表小就无所谓了,哪种都行
      

  5.   

    建用临时表。oracle支持临时表
    例如可以建个临时表temp_table
    create global temporary table temp_table
    (
      text         VARCHAR2(100),
    )
    on commit preserve rows;
    然后把pi_FileID拆开插入到这个临时表中,
    然后再做update
      

  6.   

    如果纯粹的常量,只有拆解后循环了,
    如果不是常量,数据是从一个表来,并且和update的表有关系,
    那么可以exists来替代in
      

  7.   

    create or replace type str2tblType as table of varchar2(30);
    /create or replace
    function str2tbl( p_str in varchar2, p_delim in varchar2 default ',' )
    return str2tblType
    as
        l_str      long default p_str || p_delim;
        l_n        number;
        l_data     str2tblType := str2tbltype();
    begin
        dbms_application_info.set_client_info( userenv('client_info')+1 );
        loop
            l_n := instr( l_str, p_delim );
            exit when (nvl(l_n,0) = 0);
                    l_data.extend;
                    l_data(l_data.count) := ( ltrim(rtrim(substr(l_str,1,l_n-1))) );
            l_str := substr( l_str, l_n+1 );
        end loop;
        return l_data;
    end;
    /select *
     from TABLE(cast( str2tbl( '1,2,3,4,5' ) as str2tblType) ) t
     
    /
    update t set x = 'y' where fieldid in (TABLE(cast( str2tbl( '1,2,3,4,5' ) as str2tblType) ));