我有以下过程,该过程根据输入参数更新客户端的信息。
-- Update client
create or replace procedure p_update_client (i_client_id in number, i_iin in number default null, i_full_name in varchar default null)
as
query_str varchar(200);
no_id_provided exception;
all_null_values exception;
begin
-- Handle input parameters
if i_client_id is null then
raise no_id_provided;
end if;
if i_iin is null and i_full_name is null then
raise all_null_values;
end if;
-- Base query string.
query_str := 'update t_client set';
-- Form SQL depending on the input parameters.
if i_iin is not null then
query_str := query_str || ' iin = :param1';
end if;
if i_full_name is not null then
query_str := query_str || ' full_name = :param2';
end if;
-- Add necessary where clause to identify record.
query_str := query_str || ' where client_id = :param3;';
-- Execute query.
execute immediate query_str using i_iin, i_full_name, i_client_id;
exception
when no_id_provided then
raise_application_error(-20100, 'Client_id value must not be null.');
when all_null_values then
raise_application_error(-20101, 'To update record, input parameters must not be null.');
when others then
rollback;
end p_update_client;
因此,过程的逻辑如下:如果传递的参数具有非空值,那么我将动态更新SQL并使用execute immidiate
执行它。
只要两个参数都具有非空值,此方法就可以正常工作。如果参数之一为空,则query_str
将引发SQL错误ORA-01006: bind variable does not exist
,因为query_str
中指定的参数数量与using
子句中指定的参数数量不同。
处理这种情况的更好方法是什么,也许是一种命名参数,但是据我所知,execute emmidiate
没有提供这种方法。
有任何想法吗?
答案 0 :(得分:1)
如果我是你,我不会为动态陈述而烦恼。取而代之的是,我将使用COALESCE()
(或者您可以使用NVL()
)来决定使用什么来更新列,因此您的过程将变为:
-- Update client
CREATE OR REPLACE PROCEDURE p_update_client(i_client_id IN NUMBER,
i_iin IN NUMBER DEFAULT NULL,
i_full_name IN VARCHAR DEFAULT NULL) AS
no_id_provided EXCEPTION;
all_null_values EXCEPTION;
BEGIN
-- Handle input parameters
IF i_client_id IS NULL
THEN
RAISE no_id_provided;
END IF;
IF i_iin IS NULL
AND i_full_name IS NULL
THEN
RAISE all_null_values;
END IF;
UPDATE t_client
SET iin = COALESCE(i_iin, iin),
full_name = COALESCE(i_full_name, full_name)
WHERE client_id = i_client_id;
EXCEPTION
WHEN no_id_provided THEN
raise_application_error(-20100, 'Client_id value must not be null.');
WHEN all_null_values THEN
raise_application_error(-20101, 'To update record, input parameters must not be null.');
WHEN OTHERS THEN
ROLLBACK;
END p_update_client;
/
您可能希望按照以下方式添加其他谓词:
AND (iin != COALESCE(i_iin, iin)
OR full_name != COALESCE(i_full_name, full_name))
到update语句,因此,如果传入的值与该列的当前值相同,则实际上不会进行任何更新(这会浪费时间)。