oracle 在另一个字符串变量中延迟变量计算

pbpqsu0x  于 2023-04-29  发布在  Oracle
关注(0)|答案(1)|浏览(162)

我正在尝试编写一个包含几块SQL代码的Oracle过程。在两个块之间,我想在LOG_TBL中插入一个递增的步骤号和SYSTIMESTAMP
但实际上发生的是,V_STEP_NUM只计算一次,也就是我给V_INSERT_LOG_SQL赋值的时候。因此,我只得到一堆STEP_NUMBER0的行。
但是,如果我用显式SQL替换EXECUTE IMMEDIATE V_INSERT_LOG_SQL;

EXECUTE IMMEDIATE 
    'INSERT INTO LOG_TBL (STEP_NUMBER,BEGIN_TIME) VALUES 
    ('||V_STEP_NUM||',SYSTIMESTAMP)'

则它如预期的那样工作,具有递增的步骤编号。
我做错了什么?

CREATE OR REPLACE PROCEDURE my_procedure
IS
    V_STEP_NUM NUMBER(2);
    V_INSERT_LOG_SQL CLOB;

BEGIN
    V_STEP_NUM := 0;

    V_INSERT_LOG_SQL := 'INSERT INTO LOG_TBL (STEP_NUMBER,BEGIN_TIME) VALUES ('||V_STEP_NUM||',SYSTIMESTAMP)';

    BEGIN
        V_STEP_NUM:= V_STEP_NUM + 1;
    END;    

    BEGIN
        EXECUTE IMMEDIATE V_INSERT_LOG_SQL;
    COMMIT;

    [SOME MORE SQL CODE]

    BEGIN
        V_STEP_NUM:= V_STEP_NUM + 1;
    END;    

    BEGIN
        EXECUTE IMMEDIATE V_INSERT_LOG_SQL;
        COMMIT;
    END; 

    [SOME MORE SQL CODE]
END;
j2cgzkjk

j2cgzkjk1#

在开始时将V_INSERT_LOG_SQL定义为

insert into log_tbl (step_number,begin_time) values (0,SYSTIMESTAMP)

然后就再也不改了要每次传递一个新的值,可以每次构造一个新的字符串来捕获V_INSERT_LOG_SQL的当前值,或者(对SQL缓存更好),将其作为绑定变量传递:

create or replace procedure my_procedure
as
    v_step_num number(2) := 0;
    v_insert_log_sql clob := 'insert into log_tbl (step_number,begin_time) values (:b1,SYSTIMESTAMP)';
begin    
    v_step_num := v_step_num + 1;
    execute immediate v_insert_log_sql using v_step_num;

    --[some more code]

    v_step_num := v_step_num + 1;

    execute immediate v_insert_log_sql using v_step_num;
    commit;
end;

但是,除非有比这里显示的更多的需求,否则您根本不需要动态SQL:

create or replace procedure my_procedure
as
    v_step_num number(2) := 0;
begin
    v_step_num := v_step_num + 1;
    insert into log_tbl (step_number,begin_time) values (v_step_num,SYSTIMESTAMP);

    --[some more code]

    v_step_num := v_step_num + 1;

    insert into log_tbl (step_number,begin_time) values (v_step_num,SYSTIMESTAMP);
    commit;
end;

或者更好的是,使用单独的过程进行日志记录:

create or replace procedure log_message
    ( p_step_num    in log_tbl.step_number%type
    , p_begin_time  in log_tbl.begin_time%type default systimestamp )
as
    pragma autonomous_transaction;
begin
    insert into log_tbl
    ( step_number, begin_time )
    values
    ( p_step_num, p_begin_time );

    commit;
end log_message;
create or replace procedure my_procedure
as
    v_step_num number(2) := 0;
begin    
    v_step_num := v_step_num + 1;

    log_message(v_step_num);

    --[some more code]

    v_step_num := v_step_num + 1;

    log_message(v_step_num);
end;

相关问题