如何在数字字段的条件下将逗号分隔的字符串传递给存储过程?

How to pass string of comma-separated numbers to stored procedure in condition for numeric field?

我有一个如下所示的存储过程,其中多个员工 ID 将作为逗号分隔值(多个 ID)传递。它抛出错误“ORA-01722:无效数字”。我知道这是因为为数字 ID 列传递了 varchar2 变量。但是有没有什么办法可以简单的做到这一点呢?

create or replace PROCEDURE  Fetch_Emp_Name(Emp_id in varchar2)
IS

BEGIN

select Name from EMP where id in (emp_id);

END;

您可以使用动态 sql。

create or replace PROCEDURE Fetch_Emp_Name(emp_id in varchar2) IS
v_result varchar2;
begin
    execute immediate
        'select Name from EMP where id in (' || 'emp_id' || ')'
    into
        v_result;             
end;    

您也可以使用包 dbms_sql 进行动态 sql。

更新

另一种方法。我觉得可能更好。

create or replace PROCEDURE Fetch_Emp_Name(emp_id in varchar2) IS
v_result varchar2;
begin
    select 
        Name 
    from 
        EMP 
    where 
        id in
            (
                select 
                    to_number(regexp_substr(emp_id, '[^,]+', 1, level)) 
                from 
                    dual
                connect by regexp_substr(emp_id, '[^,]+', 1, level) is not null

            );
exception
    when no_data_found then
        -- error1;
    when too_many_rows then
        -- error2;                
end;    

对不起,我之前没有正确地回答问题。如果您获得许多 ID 作为不同的参数,您也可以将名称列表检索为由逗号分隔的字符串。我把这段代码放在我处理的地方 regexp_substr 不同的名称 emp_ids 你可能会在输入参数中输入。

示例(我假设 ID 用逗号分隔)

create or replace PROCEDURE Fetch_Emp_Name(p_empid in varchar2) IS
    v_result varchar2(4000);
    v_append emp.name%type;
    v_emp    emp.emp_id%type;
    counter  pls_integer;
    i pls_integer;
    begin
       -- loop over the ids 
       counter := REGEXP_COUNT(p_empid ,'[,]') ;
       --dbms_output.put_line(p_empid);
       if counter > 0
       then 
           i := 0;
           for r in ( SELECT to_number(regexp_substr(p_empid,'[^,]+',1,level)) as mycol FROM dual CONNECT BY LEVEL <= REGEXP_COUNT(p_empid ,'[,]')+1 )
           loop
               --dbms_output.put_line(r.mycol);
               v_emp := r.mycol ;
               select name into v_append from emp where emp_id = v_emp; 
               if i < 1 
               then 
                v_result := v_append ;
               else 
                v_result := v_result ||','|| v_append ;
               end if;
               i := i + 1;             
           end loop;
       else 
           v_emp := to_number(p_empid);
           select name into v_result from emp where emp_id = v_emp; 
       end if;
       dbms_output.put_line(v_result);
       exception 
       when no_data_found 
       then 
           raise_application_error(-20001,'Not Employee found for '||v_emp||' ');
       when too_many_rows 
       then 
           raise_application_error(-20002,'Too many employees for id '||v_emp||' ');
    end;

测试

SQL> create table emp ( emp_id number, name varchar2(2) ) ;

Table created.

SQL> insert into emp values ( 1 , 'AA' );

1 row created.

SQL> insert into emp values ( 2 , 'BB' ) ;

1 row created.

SQL> commit;

SQL> insert into emp values ( 3 , 'CC' ) ;

1 row created.

SQL>  select * from emp ;

    EMP_ID NA
---------- --
         1 AA
         2 BB
         3 CC

SQL>  exec Fetch_Emp_Name('1') ;
AA

PL/SQL procedure successfully completed.

SQL> exec Fetch_Emp_Name('1,2,3') ;
AA,BB,CC

PL/SQL procedure successfully completed.

SQL>