【问题标题】:How to check if I don't have a row with current id before insert, stored procedure pl/sql如何在插入之前检查我是否没有具有当前 ID 的行,存储过程 pl/sql
【发布时间】:2019-10-27 09:42:01
【问题描述】:

我的程序从几个表中获取数据。我遍历这些结果行,并为每个临时行插入一个新行到 ZZ_TEST_RESULT 表中。在插入之前,我想验证这个 (ZZ_TEST_RESULT) 表没有我要插入的 ID (PK)。 ZZ_TEST.ID 是 PK,ZZ_TEST_RESULT.ID 也是 PK。

帮我添加条件 ZZ_TEST.ID = ZZ_TEST_RESULT.ID。

create or replace PROCEDURE "PRO_ZZZTEST"
AS
 CURSOR myCUR IS
         SELECT  ID, NAME, DESCR from ZZ_TEST;
         counter NUMBER(10) := 1;
BEGIN
  FOR ROWTEMP IN myCUR LOOP
    EXIT WHEN myCUR%NOTFOUND;
    INSERT INTO ZZ_TEST_RESULT (ID, NAME) VALUES (ROWTEMP.ID,ROWTEMP.NAME);
    COMMIT;

        DBMS_OUTPUT.PUT_LINE('Loop number = ' || counter || '; Id = '|| TO_CHAR(ROWTEMP.ID));  
     counter := counter + 1;
  END LOOP;

END PRO_ZZZTEST;

【问题讨论】:

    标签: oracle plsql unique sql-insert


    【解决方案1】:

    最简单的方法是使用ignore_row_on_dupkey_index 提示忽略重复项:

    create or replace procedure pro_zzztest as
    begin
        for cur_r in (
            select id, name, descr from zz_test
        )
        loop
            insert /*+ ignore_row_on_dupkey_index(zz_test_result(id)) */
            into zz_test_result (id, name) values (cur_r.id, cur_r.name);
        end loop;
    end;
    

    【讨论】:

    • 我总是忘记ignore_row_on_dupkey_index ,可能是因为我的大脑无法应对带有语义影响的暗示的纯粹恐惧。
    【解决方案2】:

    纯 SQL 解决方案是 MERGE。

    merge into zz_test_result ztr  
      using (select  id, name, descr 
             from zz_test) zt
      on (zt.id = ztr.id)
    when not matched then
      insert (ztr.id, ztr.name)
      values (zt.id, zt.name)
    /
    

    USING 子句是来自光标的查询。 ON 子句是您要测试的条件。 WHEN NOT MATCHED 分支意味着只有在条件为假时才插入行。


    显然,如果这是家庭作业并且强制执行 PL/SQL,那么这就是您需要提交的内容。但是,在现实生活中,在专业的企业软件中,编写交付性能所需的最少代码总是更好的选择。解决方案,这几乎总是意味着 SQL 集合操作而不是逐行过程操作。

    【讨论】:

      【解决方案3】:

      像往常一样,有不同的方法可以做到这一点。我建议内部 begin-exception-end 块(在循环内)。这样做,如果违反了主键约束,将引发并处理异常(不做任何事情),并且循环将继续执行。

      方法如下:

      create or replace procedure pro_zzztest as
      begin
        for cur_r in (select id, name, descr from zz_test) loop
          -- inner block starts here
          begin
            insert into zz_test_result (id, name) values (cur_r.id, cur_r.name);
          exception
            when dup_val_on_index then
              null;
          end;
          -- inner block ended here
        end loop;
      end;
      /
      

      【讨论】:

        【解决方案4】:

        记录错误方法。
        1) 设置。

        begin
        DBMS_ERRLOG.CREATE_ERROR_LOG ('ZZ_TEST_RESULT');
        end;
        

        脚本将为 dml 错误创建专用表。名称为 ERR$_+table_name,(ERR$_ZZ_TEST_RESULT)
        2)改变你的插入,

         INSERT INTO ZZ_TEST_RESULT (ID, NAME) VALUES (ROWTEMP.ID,ROWTEMP.NAME) log errors ('optional message')  REJECT LIMIT UNLIMITED
        

        3) 验证错误表。

        select * from ERR$_ZZ_TEST_RESULT
        

        注意,此方法将捕获所有类型的 DML 异常,而不仅仅是 dup val 错误

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-05
          • 2020-04-22
          • 1970-01-01
          相关资源
          最近更新 更多