Oracle Equivalente a MySQL INSERT IGNORA?

Devo aggiornare una query in modo che controlli che una voce duplicata non esiste prima dell’inserimento. In MySQL posso semplicemente usare INSERISCI IGNORE in modo che se si trova un record duplicato, salta semplicemente l’inserto, ma non riesco a trovare un’opzione equivalente per Oracle. Eventuali suggerimenti?

Controlla la dichiarazione MERGE. Questo dovrebbe fare ciò che vuoi – è la clausola WHEN NOT MATCHED che farà questo.

Fare a Oracle mancanza di supporto per una clausola true VALUES () la syntax per un singolo record con valori fissi è piuttosto maldestro però:

 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); 

Un approccio diverso (se si sta ad esempio facendo il caricamento di massa da una tabella diversa) consiste nell’utilizzare la funzione “Registrazione degli errori” di Oracle. La dichiarazione sarebbe simile a questa:

  INSERT INTO your_table (col1, col2, col3) SELECT c1, c2, c3 FROM staging_table LOG ERRORS INTO errlog ('some comment') REJECT LIMIT UNLIMITED; 

Successivamente tutte le righe che avrebbero generato un errore sono disponibili nel errlog della tabella. È necessario creare errlog tabella di errlog (o qualsiasi altro nome che si sceglie) prima di eseguire l’inserimento utilizzando DBMS_ERRLOG.CREATE_ERROR_LOG .

Vedi il manuale per i dettagli

Se sei su 11g puoi utilizzare il suggerimento 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. 

Non penso ci sia, ma per risparmiare tempo puoi provare l’inserto e ignorare l’inevitabile errore:

 begin insert into table_a( col1, col2, col3 ) values ( 1, 2, 3 ); exception when dup_val_on_index then null; end; / 

Questo ignorerà solo le eccezioni sollevate specificamente dalla chiave primaria duplicata o dai vincoli di chiave univoci; tutto il resto verrà sollevato normalmente.

Se non vuoi farlo, devi prima selezionare dal tavolo, il che non è poi così efficiente.

Un’altra variante

 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) 

o potresti farlo

 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 

Una soluzione semplice

 insert into t1 select from t2 where not exists (select 1 from t1 where t1.id= t2.id) 

Che ne dici di aggiungere semplicemente un indice con tutti i campi che devi controllare per i duplicati e dire che deve essere unico? Salva un controllo di lettura.

Questo non è mio, ma è diventato molto utile quando si utilizza sqlloader:

  1. crea una vista che punti alla tua tabella:

     CREATE OR REPLACE VIEW test_view AS SELECT * FROM test_tab 
  2. crea il trigger:

     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; 
  3. e nel file ctl, invece, inserisci nella vista:

     OPTIONS(ERRORS=0) LOAD DATA INFILE 'file_with_duplicates.csv' INTO TABLE test_view FIELDS TERMINATED BY ',' (id, field1)