【发布时间】:2023-12-25 20:38:01
【问题描述】:
我需要更新一个查询,以便在插入之前检查是否存在重复条目。在 MySQL 中,我可以只使用 INSERT IGNORE,这样如果发现重复记录,它就会跳过插入,但我似乎找不到 Oracle 的等效选项。有什么建议吗?
【问题讨论】:
标签: oracle insert duplicates
我需要更新一个查询,以便在插入之前检查是否存在重复条目。在 MySQL 中,我可以只使用 INSERT IGNORE,这样如果发现重复记录,它就会跳过插入,但我似乎找不到 Oracle 的等效选项。有什么建议吗?
【问题讨论】:
标签: oracle insert duplicates
如果您使用的是 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.
【讨论】:
查看 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 中找到。在使用 DBMS_ERRLOG.CREATE_ERROR_LOG 运行插入之前,您需要手动创建 errlog 表(或您选择的任何名称)。
详见说明书
【讨论】:
INSERTs,这是 Bad Programmer 所要求的。但是感谢链接,我不知道它不适用于 PK 的更新(我只将它用于插入)
FROM 关键字替换为USING 关键字吗?如果需要,请查看*.com/questions/16414747/…。
我认为除了节省时间之外,您可以尝试插入并忽略不可避免的错误:
begin
insert into table_a( col1, col2, col3 )
values ( 1, 2, 3 );
exception when dup_val_on_index then
null;
end;
/
这只会忽略重复主键或唯一键约束特别引发的异常;其他一切都会照常进行。
如果您不想这样做,则必须先从表格中进行选择,这实际上效率不高。
【讨论】:
executeUpdate() 返回了1,我希望它返回 0,因为没有更新任何行。这使我无法理解在使用此 for 插入时是否插入了新数据。
INSERT 并以您使用的任何语言捕获任何异常。这个问题的每个答案都会返回1。
另一种变体
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
【讨论】:
一个简单的解决方案
insert into t1
select from t2
where not exists
(select 1 from t1 where t1.id= t2.id)
【讨论】:
这不是我的,但在使用 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)
【讨论】:
如何简单地添加一个索引,其中包含您需要检查是否存在欺骗的任何字段并说它必须是唯一的?保存读取检查。
【讨论】:
另一个“不存在的地方”——使用双重的变体......
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');
【讨论】: