Мне нужно обновить запрос, чтобы он проверял, что дублирующая запись не существует до вставки. В MySQL я могу просто использовать INSERT IGNORE, чтобы при обнаружении дублированной записи она просто пропускает вставку, но я не могу найти эквивалентную опцию для Oracle. Любые предложения?
Oracle эквивалентен MySQL INSERT IGNORE?
Ответ 1
Проверьте утверждение MERGE. Это должно делать то, что вы хотите - это предложение WHEN NOT MATCHED
, которое сделает это.
Предоставить Oracle отсутствие поддержки для действительного предложения VALUES() синтаксис для одной записи с фиксированными значениями довольно неуклюжий:
MERGE INTO your_table yt
USING (
SELECT 42 as the_pk_value,
'some_value' as some_column
FROM dual
) t on (yt.pk = t.the_pke_value)
WHEN NOT MATCHED THEN
INSERT (pk, the_column)
VALUES (t.the_pk_value, t.some_column);
Другой подход (если вы, например, выполняете массовую загрузку из другой таблицы), должен использовать средство "Логгинга ошибок" Oracle. Заявление будет выглядеть так:
INSERT INTO your_table (col1, col2, col3)
SELECT c1, c2, c3
FROM staging_table
LOG ERRORS INTO errlog ('some comment') REJECT LIMIT UNLIMITED;
Впоследствии все строки, которые вывели бы ошибку, доступны в таблице errlog
. Вам нужно создать эту таблицу errlog
(или любое другое имя, которое вы выберете) вручную, прежде чем запускать вставку с помощью DBMS_ERRLOG.CREATE_ERROR_LOG
.
Подробнее см. в руководстве.
Ответ 2
Если вы на 11g, вы можете использовать подсказку IGNORE_ROW_ON_DUPKEY_INDEX:
SQL> create table my_table(a number, constraint my_table_pk primary key (a));
Table created.
SQL> insert /*+ ignore_row_on_dupkey_index(my_table, my_table_pk) */
2 into my_table
3 select 1 from dual
4 union all
5 select 1 from dual;
1 row created.
Ответ 3
Я не думаю, что есть, но чтобы сэкономить время, вы можете попробовать вставить и проигнорировать неизбежную ошибку:
begin
insert into table_a( col1, col2, col3 )
values ( 1, 2, 3 );
exception when dup_val_on_index then
null;
end;
/
Это будет игнорировать исключения, возникающие, в частности, путем дублирования первичного ключа или уникальных ограничений ключа; все остальное будет поднято как обычно.
Если вы не хотите этого делать, вам сначала нужно выбрать из таблицы, что на самом деле не так эффективно.
Ответ 4
Другой вариант
Insert into my_table (student_id, group_id)
select distinct p.studentid, g.groupid
from person p, group g
where NOT EXISTS (select 1
from my_table a
where a.student_id = p.studentid
and a.group_id = g.groupid)
или вы могли бы сделать
Insert into my_table (student_id, group_id)
select distinct p.studentid, g.groupid
from person p, group g
MINUS
select student_id, group_id
from my_table
Ответ 5
Простое решение
insert into t1
select from t2
where not exists
(select 1 from t1 where t1.id= t2.id)
Ответ 6
Как просто добавить индекс с любыми полями, которые нужно проверить для обмана и сказать, что он должен быть уникальным? Сохраняет проверку чтения.
Ответ 7
Это не мое, но очень полезно при использовании sqlloader:
-
создать представление, указывающее на таблицу:
CREATE OR REPLACE VIEW test_view AS SELECT * FROM test_tab
-
создать триггер:
CREATE OR REPLACE TRIGGER test_trig INSTEAD OF INSERT ON test_view FOR EACH ROW BEGIN INSERT INTO test_tab VALUES (:NEW.id, :NEW.name); EXCEPTION WHEN DUP_VAL_ON_INDEX THEN NULL; END test_trig;
-
и в файле ctl вместо этого вставьте вместо этого:
OPTIONS(ERRORS=0) LOAD DATA INFILE 'file_with_duplicates.csv' INTO TABLE test_view FIELDS TERMINATED BY ',' (id, field1)
Ответ 8
еще одно "где не существует" -variant с использованием двойного...
insert into t1(id, unique_name)
select t1_seq.nextval, 'Franz-Xaver' from dual
where not exists (select 1 from t1 where unique_name = 'Franz-Xaver');