【问题标题】:Oracle dynamic SQL with null parameters带空参数的 Oracle 动态 SQL
【发布时间】:2019-03-15 06:23:07
【问题描述】:

我有以下过程,根据输入参数更新客户端的信息。

-- 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 不提供。 有任何想法吗?

【问题讨论】:

    标签: sql oracle plsql oracle11g dynamic-sql


    【解决方案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))
    

    到更新语句,这样如果传入的值与列的当前值相同,则实际上不会发生更新(这会浪费时间)。

    【讨论】:

    • 这真是一个神点!我没有考虑这些功能。我想,我会重写我的函数。谢谢)
    猜你喜欢
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2017-09-10
    相关资源
    最近更新 更多