【问题标题】:PL/SQL Oracle - Insert ID from Table 2 in Table 1 based on Name as key, which may be duplicate and update Table 2 if Name not foundPL/SQL Oracle - 根据名称作为键在表 1 中插入表 2 中的 ID,如果未找到名称,可能重复并更新表 2
【发布时间】:2017-12-25 03:50:51
【问题描述】:

PL/SQL - 根据名称作为键将表 2 中的 ID 插入表 1 中,如果在 Oracle 中找不到名称,则可能重复并更新表 2。

我必须创建一个执行上述任务的存储过程

给定表 1:TEST1

Name |  Data  | ID |
Tim  |  Test1 |    |
Jim  |  Test2 |    |
Jim  |  Test3 |    |
Roy  |  Test4 |    |
Matt |  Test5 |    |

给定表 2:TEST2(ID 自动生成)

ID   |  Name  |
23   |  Tim   | 
24   |  Jim   | 
20   |  Matt  |

需要结果表为:

Name |  Data  | ID |
Tim  |  Test1 | 23 |
Jim  |  Test2 | 24 |
Jim  |  Test3 | 24 |
Roy  |  Test4 | x  |
Matt |  Test5 | y  |

如果在 TEST2 中找不到名称,则 x、y 是 Roy 和 Matt 新生成的 ID

我写了以下代码:

MERGE INTO TEST1 b
USING (
  SELECT ID, NAME FROM TEST2) e
ON (b.NAME = e.NAME)
WHEN MATCHED THEN
  UPDATE SET b.CODE = E.ID
WHEN NOT MATCHED THEN
  INSERT (b.CODE)
  VALUES ('NONE');

产生

Name |  Data  | ID |
Tim  |  Test1 | 23 |
Jim  |  Test2 | 24 |
Jim  |  Test3 | 24 |
Roy  |  Test4 | -  |
Matt |  Test5 | -  |

我没有得到在 TEST2 中同时插入新行并获取数据的逻辑。

请帮忙!!

【问题讨论】:

  • 表 TEST2 的新 ID 值是如何生成的?
  • 这似乎是一个有缺陷的过程。您可能希望将第二个表中的 ID 列作为主键,并在第一个表中使用它。在这种情况下,您也不应该将名称存储在第一个表中。现在(假设您正在解决该问题):如果相同的名称在第二个表中出现多次怎么办?然后:首先您应该使用缺少的名称更新第二个表,然后使用 ID 更新第一个表。 “同时”是错误的想法;您必须分两步完成。在此期间,您需要锁定这两个表。
  • @krokodilko ID 是通过 TEST2 表中的 auto_increment 生成的
  • @mathguy 是的,我想你是对的......我需要另一个 SQL 来处理不匹配的情况......会继续挖掘。
  • @NishantPatel 你想将它实现为触发器还是 PL/SQL 程序? (我的意思是它是一次性任务,还是您想在每次插入时即时完成)。您想如何为 TEST2 表中未找到的行生成 ID?

标签: sql oracle merge


【解决方案1】:

请试一试(ad-hoc PL/SQL,但测试后可以改成procedure)

DECLARE
  TYPE test_cur_type IS REF CURSOR RETURN test1%ROWTYPE;
  test_cur test_cur_type;
  test_row test1%rowtype;
BEGIN
  OPEN test_cur FOR SELECT name, data, id FROM test1;
  LOOP
    FETCH test_cur INTO test_row;
    EXIT WHEN test_cur%NOTFOUND;
    INSERT INTO test3 (name, data, id)
    VALUES (test_row.name, test_row.data,
      NVL(SELECT id FROM test2 
           WHERE name=test_row.name AND ROWNUM <= 1, test_sequence.nextval));
  END LOOP;
 CLOSE test_cur;
END;

test_sequence 在哪里

 CREATE SEQUENCE test_sequence
    INCREMENT BY 1 
    MAXVALUE 5000
    CACHE 20;

并且两个表 test2 和 test3 对id 列都有以下定义

id number default test_sequence.nextval

此脚本允许您在每个行级别实现任何复杂逻辑,并且可以通过批量更新(避免 pl/sql - sql 上下文切换开销)进一步优化(如果需要(避免过早优化))

【讨论】:

    【解决方案2】:

    我想出了一个解决方案,可能很天真,但现在我已经完成了我的任务。下面是代码

    create or replace procedure TestProc as
    begin
    MERGE INTO TEST2 T2
       USING (SELECT DISTINCT NAME FROM TEST1) T1
             ON (T1.NAME = T2.NAME)
       WHEN NOT MATCHED THEN
           INSERT (T2.NAME) VALUES (T1.NAME);
    MERGE INTO TEST1 b
    USING (
      SELECT ID, NAME
      FROM TEST2) e
    ON (b.NAME = e.NAME)
    WHEN MATCHED THEN
      UPDATE SET b.CODE = E.ID
    WHEN NOT MATCHED THEN
      INSERT (b.CODE)
      VALUES ('NONE');
     end;
    

    欢迎进一步的优化和想法。谢谢!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多