PL / SQL加速长函数

时间:2018-07-09 20:53:07

标签: regex oracle plsql

我希望加快以下PL / SQL功能的速度。目前,它已经运行了2多个小时,没有完成的迹象。我们中止了那个,然后尝试以20的退出次数再次尝试,但仍然没有任何迹象表明实际完成。

我们正在通过SQLDeveloper 17.3运行它们,并且(4)表中的每个表都有大约15,000行。

目标是获取我们数据库中的所有SSN,并将第一个字符更改为非法字符,将后两个字符更改为随机的A-Z组合。然后,我们必须在使用它的每个表中更新该SSN(4)。

declare
    v_random varchar2(2); 
    v_origin_ssn varchar2(100);
    v_working_start varchar2(100);
    v_working_middle varchar2(100);
    v_new_ssn varchar2(100);
begin

    for o in (
        select distinct ssn  --loop all rows in tbl_customer
        from program_one.tbl_customer
    )
    loop
        if regexp_like(o.ssn, '^[A-Za-z9].*[A-Z]$') then continue; --if this is already scrambled, skip
        else 
            select dbms_random.string('U', 2) --create random 2 cap letters
                into v_random
            from dual;

            v_origin_ssn := o.ssn; --set origin ssn with the existing ssn

            if regexp_like(o.ssn, '^[A-Za-z]') --if first char is already alpha, leave it alone, otherwise 9
                then v_working_start := substr(o.ssn, 1, 1);
                else v_working_start := 9; 
            end if;

            v_working_middle := substr(o.ssn, 2, 6); --set middle ssn with the unchanged numbers

            v_new_ssn := v_working_start||v_working_middle||v_random; --create new sanitized ssn

            update program_one.tbl_customer --update if exists in tbl_customer
            set ssn = v_new_ssn
            where ssn = v_origin_ssn;

            commit;

            update program_one.tbl_mhc_backup --update if exists ssn tbl_mhc_backup
            set ssn = v_new_ssn
            where ssn = v_origin_ssn;

            commit;

            update program_two.tbl_waiver --update if exists ssn tbl_waiver
            set ssn = v_new_ssn
            where ssn = v_origin_ssn;

            commit;

            update program_two.tbl_pers --update if exists in tbl_pers
            set ssan = v_new_ssn
            where ssan = v_origin_ssn;

            commit;

        end if;

        --dbms_output.put_line(v_origin_ssn||' : '||v_new_ssn); --output test string to verify working correctly

    end loop;

end;

1 个答案:

答案 0 :(得分:2)

我会在普通SQL中不使用任何函数来完成此操作:

使用新旧ssn创建表:

CREATE TABLE tmp_ssn AS
  SELECT ssn, '9'||substr(ssn,2,6)||dbms_random.string('U',2) as new_ssn
    FROM (SELECT distinct ssn FROM program_one.tbl_customer);
CREATE UNIQUE INDEX ui_tmp_ssn ON tmp_ssn(ssn, new_ssn);
EXEC DBMS_STATS.GATHER_TABLE_STATS(null,'tmp_ssn');

...,然后一张一张地更新表:

MERGE INTO program_one.tbl_customer z USING tmp_ssn q ON (z.ssn=q.ssn)
 WHEN MATCHED THEN UPDATE z.ssn = q.new_ssn;
COMMIT;

MERGE INTO program_one.tbl_mhc_backup z USING tmp_ssn q ON (z.ssn=q.ssn)
 WHEN MATCHED THEN UPDATE z.ssn = q.new_ssn;
COMMIT;

etc

如果那仍然很慢,我会做

RENAME tbl_customer to tbl_customer_old;
CREATE TABLE tbl_customer as
  SELECT s.new_ssn as ssn, t.col1, t.col2, ... , t.coln
    FROM tbl_customer_old t JOIN tmp_ssn s USING(ssn);
DROP TABLE tbl_customer_old;