如何在数字字段的条件下将逗号分隔的数字字符串传递给存储过程?
Posted
技术标签:
【中文标题】如何在数字字段的条件下将逗号分隔的数字字符串传递给存储过程?【英文标题】:How to pass string of comma-separated numbers to stored procedure in condition for numeric field? 【发布时间】:2020-07-31 13:10:31 【问题描述】:我有一个如下所示的存储过程,其中多个员工 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;
【问题讨论】:
如果您传递多个 ID,那么您希望它找到多个名称,对吗?您的程序将如何处理这些? 包括样本数据和样本调用(具有多个值)和预期结果会有所帮助。另外,值的字符串来自哪里 - 可以在调用方更改为值的集合吗? @Prabakaran,那么您是说输入参数中可能会传递这么多 emp_ids 以逗号分隔?? 是的,我期待多个名称作为输出。使用输出名称,我将在另一个表中插入。我只能调用字符串变量。样本将类似于 Exec Fetch_Emp_Name('1,2,3'); @Prabakaran,我发布了一个新答案,其中我将不同的 ID 处理到同一个 p_empid 变量中。请随意评论答案中的任何内容 【参考方案1】:你可以使用动态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,那么它会(大概)找到多个名字;当您尝试将它们全部放入标量v_result
字符串时,会出现太多行错误。
@AlexPoole 是的,没错。你也需要处理异常。我刚刚讲述了获得预期结果的方法。
@AntonTokmakov - 如果发生这种情况,这与处理异常无关;问题是字符串有多个 ID,所以您期望它会在表中找到多行,不是吗?
sql注入。 Antoshka,您应该使用绑定变量。不需要 dbms_sql。
@AlexPoole 我添加了另一个答案,可能会更好。【参考方案2】:
抱歉,我没有以正确的方式回答问题。如果您将许多 ID 作为不同的参数,您也可以将名称列表检索为用逗号分隔的字符串。我把这段代码放在了regexp_substr
处理的地方,你可以在输入参数中输入不同的emp_id的名称。
示例(我假设 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>
【讨论】:
以上是关于如何在数字字段的条件下将逗号分隔的数字字符串传递给存储过程?的主要内容,如果未能解决你的问题,请参考以下文章