Как проверить, нет ли у меня строки с текущим идентификатором перед вставкой, хранимая процедура pl / sql - PullRequest
1 голос
/ 27 октября 2019

Моя процедура получает данные из нескольких таблиц. Я перебираю эти результирующие строки и для каждой временной строки вставляю новую строку в таблицу ZZ_TEST_RESULT. Перед вставкой я хочу убедиться, что в этой (ZZ_TEST_RESULT) таблице нет идентификатора (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;

Ответы [ 4 ]

4 голосов
/ 27 октября 2019

Самый простой подход - игнорировать дубликаты, используя подсказку 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;
1 голос
/ 27 октября 2019

Чистое решение 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, а не построчные процедурные операции.

0 голосов
/ 28 октября 2019

Метод регистрации ошибок.
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

0 голосов
/ 27 октября 2019

Как обычно, есть разные способы сделать это. Я бы предложил внутренний блок 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;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...