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

Database 使用pl/sql查找表中的多个值并在不存在时插入的过程,database,oracle,plsql,cursor,procedure,Database,Oracle,Plsql,Cursor,Procedure,我有这个表和这个关系:单位-->费用-->角色 UNIT_CODE | CHARGE_CODE | ROLE_CODE 0101010001 | 9023409 | AZAAAA 0102010002 | 8023409 | AXAAAB 0103010003 | 7023409 | ACAAAC 0104010004 | 6023409 | AVAAA

我有这个和这个关系:单位-->费用-->角色

UNIT_CODE    |    CHARGE_CODE    |    ROLE_CODE
0101010001   |     9023409       |    AZAAAA
0102010002   |     8023409       |    AXAAAB
0103010003   |     7023409       |    ACAAAC
0104010004   |     6023409       |    AVAAAV
0101010001   |     5023409       |    NEWROL
0102010002   |     4023409       |    AZAAAA
此表几乎有2000行/行

因此,情况如下:

我必须为特定的90单元代码插入一个特定的角色\u COD(
NEWROL
)。但这个角色适用于特定的单位负责人

示例:我必须为该单元插入角色代码=
新角色
0101010001
和该费用
5023409

  • 因此,我必须检查:

  • 如果单位
    0101010001
    已经存在对
  • 如果单位/费用
    0101010001/5023409
    关系已经存在对
  • 如果已存在装置/充电/rol
    0101010001/5023409/NEWROL
如果3个问题的答案是肯定的,我必须检查其他单位/费用组合:

0102010002/4023409

  • 如果单位
    0102010002
    已经存在对
  • 如果单位/费用
    0102010002/4023409
    关系已经存在对
  • 如果装置/充电/rol
    0102010002/4023409/NEWROL
    已经存在没有
  • 因此,我必须在表中插入角色:NEWROL用于此单位/费用,并检查其他单位和费用

    注意:单位是唯一的,但有些单位具有相同/多重角色或费用


    我必须检查90个单位,我需要一个程序来收取
    单位代码
    费用
    进行验证,必要时插入
    角色代码

    这里是一个纯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' )
    /
    
    子查询返回一组没有
    角色的
    (单位代码、费用代码)
    。如果确实需要存储过程,可以调整上限WHERE子句以使用PL/SQL参数


    下面是一个将此查询过程化的解决方案。它使用SQL类型传递目标
    (单位代码、费用代码)
    对:

    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> 
    
    最大的挑战仍然是将目标密钥从文档中获取到数据库中。我个人会选择一个程序员的文本编辑器,比如记事本++。这使得使用regex search'n'replace将值列表转换为这些类型赋值变得轻而易举

    search: ([0-9]+)\t([0-9]+)
    replace: unit_charge_t\('\1', \z\)
    
    另一种界面是使用外部表,将
    .docx
    更改为
    .csv
    文件


    有许多可能的解决办法;哪个最合适取决于您的情况的特殊性。

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

    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;
    

    这90个
    单位代码
    费用
    组合的值来自哪里?另一张桌子?不,他们来自同一张桌子。但是我已经确定了90号单位代码,它们是我必须检查的特定费用@APCUNIT\u代码不是唯一的<代码>0101010001
    重复了您是对的@MahendarMahi,但在此表中,我们将找到相同的
    单位代码
    ,差异
    代码费用
    角色代码
    。这是一个关系表。所以,我想知道,当我运行它时,我是否可以制作一个程序,使用
    单位代码,充电\u代码
    ,并测试他们是否有
    NEWROL
    ,如果它没有插入
    。这是个好主意,但这样我必须把90个条件放在哪里?您知道运行获取值的过程吗​​我定义的单位和功能是什么@APC@spikeTJ-我问过你如何存储这些值,但你没有给出实际答案。所以我不确定你希望我提出什么建议。如果这是一个一次性的练习,您可以将WHERE子句克隆编辑90次。如果你想让这是可重用的,你需要提供更多的细节。是的,我希望这是可重用的。我有一个
    unit\u code
    和相应的
    code\u费用
    列表,他们必须在其中插入
    NEWROL
    。我正在尝试执行一个过程,为相应的
    单元代码、费用代码插入
    角色
    。抱歉,如果我解释得不好@APC。显然我没有很好地解释自己。你有一张单子。您希望对该列表中的每个条目执行检查和更新。但是这个列表是什么格式的呢?该列表上的条目是否以某种方式存储在数据库中,还是在数据库之外(在电子表格、电子邮件、您的头部)?我所说的可重复使用是指将来某个时候,你是否需要为不同的(单位代码、费用代码)对列表重复这个练习?好的,我在.docx文件中有这个列表。所以我想要程序,因为这样我只需要复制de
    unit\u code
    charge
    ,如果我要调用
    程序,并将其作为参数传递。是的,也许我必须为不同的列表重复一遍,但始终使用以下参数:
    UNIT\u code,CHARGE\u code
    @APC