使用 pl/sql 在 table 中查找多个值并在不存在时插入的过程

Procedure to find multiples values in a table and insert if doesnt exist using pl/sql

我有这个 table 这个关系:UNIT --> CHARGE ---> 角色

UNIT_CODE    |    CHARGE_CODE    |    ROLE_CODE
0101010001   |     9023409       |    AZAAAA
0102010002   |     8023409       |    AXAAAB
0103010003   |     7023409       |    ACAAAC
0104010004   |     6023409       |    AVAAAV
0101010001   |     5023409       |    NEWROL
0102010002   |     4023409       |    AZAAAA

这个table已经快2.000了rows/line。

所以,情况是这样的:

我必须为特定的 90 unit_code 插入特定的 ROLE_COD (NEWROL)。但是这个角色申请了具体负责的单位。

示例:我必须插入 role_code = NEWROLE 为此 单位 0101010001 和这个 charge 5023409

如果 3 个问题的答案是肯定的,我必须检查其他 单位/费用 组合:

0102010002 / 4023409

  1. 如果单位 0102010002已经存在? - 是
  2. 如果单位/费用0102010002 / 4023409关系已经存在? - 是
  3. 如果unit/charge/rol0102010002 / 4023409 / NEWROL已经存在? - 否

所以我必须在 table 中插入角色:为此 units/charge 的 NEWROL 并检查其他单位并收费。

注意:这些单位是独一无二的,但有些单位具有 same/multiples 角色或职责。

我必须检查 90 个单位,我需要一个程序来采用 unit_codecharge 进行验证并在必要时插入 role_code

这是一个纯粹的 SQL 解决方案:

insert into your_table t
select unit_code, charge_code, 'NEWROL'
from 
    ( select unit_code, charge_code from your_table
      where (unit_code = '0101010001' and charge_code = 5023409)
      or    (unit_code = '0102010002' and charge_code = 4023409)
      minus
      select unit_code, charge_code from your_table
      where  role_code = 'NEWROL' )
/

子查询 returns (unit_code, charge_code) 的集合没有 role_code='NEWROL'。如果您确实需要存储过程,可以调整上面的 WHERE 子句以使用 PL/SQL 参数。


这是程序化此查询的一种解决方案。它使用 SQL 类型来传递目标 (unit_code, charge_code) 对:

create or replace type unit_charge_t as object
    (unit_code varchar2(10), charge_code number);
/
create or replace type unit_charge_nt as table of unit_charge_t;
/

这是一个简单的概念证明。您需要添加日志记录、异常处理等。

create or replace procedure ins_your_table
    (p_recs in unit_charge_nt
     , p_new_role in your_table.role_code%type := 'NEWROL')
as
begin
    insert into your_table t
    select unit_code, charge_code, 'NEWROL'
    from 
        ( select unit_code, charge_code from your_table
          where (unit_code, charge_code) in (select * from table(p_recs))
    minus
    select unit_code, charge_code from your_table
    where  role_code = 'NEWROL' );
    dbms_output.put_line('inserted records = '||sql%rowcount);
end ins_your_table;
/

调用示例:

SQL> set serveroutput on
SQL> declare 
  2      tgt_rows unit_charge_nt  
  3          := unit_charge_nt ( unit_charge_t('0101010001', 5023409)
  4                              , unit_charge_t('0102010002', 4023409) );
  5  begin
  6      ins_your_table(tgt_rows);   
  7  end;
  8  /
inserted records = 1

PL/SQL procedure successfully completed.

SQL> 

最大的挑战仍然是将文档中的目标键输入到数据库中。我个人会选择程序员的文本编辑器,例如 NotePad++。这将使使用正则表达式 search'n'replace 将值列表转换为那些类型赋值变得轻而易举。

search: ([0-9]+)\t([0-9]+)
replace: unit_charge_t\('', \z\)

另一种接口是使用外部 table,将 .docx 更改为 .csv 文件。

有许多可能的解决方案;哪个最合适table要看你的具体情况。

我使用这个查询解决了这个问题:

CREATE OR REPLACE PROCEDURE my_procedure
    (in_unit_code IN table_1.unit_code%TYPE,
     in_charge_code IN table_1.charge_code%TYPE,
     in_role_code IN table_1.role_code%TYPE)
    AS
        BEGIN
        trace('my_procedure_p', 'a', 'Role Insert starting');
            INSERT INTO table_1 (
                unit_code,
                charge_code,
                role_code
                ) values (
               in_unit_code,
               in_charge_code,
               in_role_code
           );
           trace('my_procedure_p', 'a',
           'It is inserted correctly. ROLE: ' || in_role_code ||
           ', UNIT: ' || in_unit_code ||
           ', CHARGE: ' || in_charge_code ||
           ' Date: ' || SYSDATE);    
           COMMIT;
    --Note: If the insert is successful i COMMIT, but if records are duplicates i captured with this exception.
    EXCEPTION
    WHEN dup_val_on_index THEN
    ptraza('my_procedure_p', 'a',
    'Attention, ROLE: ' || in_role_code ||
    ' It is already in the table UNIT: ' || in_unit_code ||
    ', CHARGE: ' || in_charge_code);
END my_procedure;

我这样打电话:

BEGIN
    my_procedure('0000000004','CHARGE01','ROLECODE01');
    my_procedure('0000000003','CHARGE02','ROLECODE01');
    my_procedure('0000000002','CHARGE00','ROLECODE03');
    my_procedure('0000000001','CHARGE00','ROLECODE03');
END;