代码之家  ›  专栏  ›  技术社区  ›  Konstantin Chsherbakov

带空参数的Oracle动态SQL

  •  0
  • Konstantin Chsherbakov  · 技术社区  · 6 年前

    -- 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;
    

    execute immidiate . 只要这两个参数都具有非空值,就可以正常工作。如果其中一个参数为null,则 query_str 将引发SQL错误 ORA-01006: bind variable does not exist 查询\u str using 条款。

    处理这种情况最好的方法是什么,也许是一些命名参数,但我知道, execute emmidiate 没有提供。 有什么想法吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Boneist    6 年前

    如果我是你的话,我就不会为动态陈述而烦恼了。相反,我会用 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))
    

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