【问题标题】:Procedure to find multiples values in a table and insert if doesnt exist using pl/sql使用 pl/sql 在表中查找多个值并在不存在时插入的过程
【发布时间】:2015-11-25 17:36:24
【问题描述】:

我有这个 table 与这种关系:UNIT --> CHARGE ---> ROLE

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

此表有近 2.000 行/行。

所以,情况如下:

我必须为特定的 90 unit_code 插入特定的 ROLE_COD (NEWROL)。但是这个角色适用于特定收费的单位。

示例:我必须为此 units 0101010001 和此 charge 5023409 插入 role_code = NEWROLE p>

  • 所以,我必须检查:

    1. 如果单位0101010001 已经存在? - 是的
    2. 如果单位/费用0101010001 / 5023409关系已经存在? - 是的
    3. 如果unit/charge/rol0101010001 / 5023409 / NEWROL已经存在? - 是的

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

0102010002 / 4023409

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

所以我必须在表格中插入角色:NEWROL 为这个单位/收费并检查其他单位和收费。

注意:单位是独一无二的,但有些单位具有相同/多重角色或冲锋。

我必须检查 90 个单位,我需要一个程序来获取 unit_code 和 charge 进行验证并在必要时插入 role_code。

【问题讨论】:

  • 这九十个 unit_code , charge 组合的值从何而来?另一张桌子?
  • 不,他们来自同一张桌子。但我已经确定了 90 个unit_code 和他们特定的charge,我必须检查。 @APC
  • UNIT_CODE 不是 unique 。 0101010001 重复
  • 你说得对@MahendarMahi,但在此表中会找到相同的unit_code,但code_charge 和role_code 不同。这是一个关系表。所以,我想知道我是否可以在运行它时创建一个程序,使用unit_code, charge_code 并测试他们是否有NEWROL,如果它没有插入table。

标签: database oracle plsql cursor procedure


【解决方案1】:

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

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;

【讨论】:

    【解决方案2】:

    这是一个纯 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' )
    /
    

    子查询返回没有role_code='NEWROL' 的(unit_code, charge_code) 集合。如果您确实需要存储过程,可以调整上面的 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++。这将使使用 regex search'n'replace 将值列表转换为这些类型分配变得轻而易举。

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

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

    有许多可能的解决方案;哪个最合适取决于您的具体情况。

    【讨论】:

    • 这是个好主意,但是这样我必须把 90 放在哪里条件?你知道一个程序在运行时取我定义的单位和函数的值吗? @APC
    • @spikeTJ - 我确实问过你是如何存储这些值的,但你没有给出实际答案。所以我不确定你希望我提出什么建议。如果这是一次性练习,您可以克隆'n'编辑 WHERE 子句九十次。如果您希望它可重复使用,您需要提供更多详细信息。
    • 是的,我希望它可以重复使用。我有一个unit_code 和各自的code_charge 列表,他们必须在其中插入NEWROL。我正在尝试执行为相应的UNIT_CODE, CHARGE_CODE 插入ROLE 的过程。对不起,如果我没有很好地解释@APC。
    • 显然我没有很好地解释自己。你有一个清单。您想对该列表中的每个条目执行检查和更新。但是那个列表是什么格式的呢? 该列表中的条目 是否以某种方式存储在数据库中,或者它们是否在数据库之外(在电子表格、电子邮件、您的头脑中)?我所说的可重用是指您是否需要在未来某个时间重复此练习以获得不同的 (UNIT_CODE, CHARGE_CODE) 对列表?
    • 好的,我有一个 .docx 文件中的列表。所以我想要程序,因为这样我只需复制 de unit_code 和 charge 如果我要调用 procedure 并将其作为参数传递。是的,也许我必须为不同的列表再次重复,但始终使用此参数:UNIT_CODE, CHARGE_CODE@APC
    猜你喜欢
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多