Je dois mettre à jour une requête afin qu'elle vérifie qu'une entrée en double n'existe pas avant l'insertion. Dans MySQL, je peux simplement utiliser INSERT IGNORE pour que, si un enregistrement en double est trouvé, il saute simplement l'insertion, mais je ne trouve pas l'option équivalente pour Oracle. Aucune suggestion?
Découvrez la déclaration MERGE. Cela devrait faire ce que vous voulez - c'est la clause WHEN NOT MATCHED
qui le fera.
En raison du manque de prise en charge par Oracle d'une vraie clause VALUES (), la syntaxe d'un enregistrement unique avec des valeurs fixes est assez maladroite:
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);
Une approche différente (si vous effectuez par exemple un chargement en vrac à partir d’une autre table) consiste à utiliser la fonction "Enregistrement des erreurs" d’Oracle. La déclaration ressemblerait à ceci:
INSERT INTO your_table (col1, col2, col3)
SELECT c1, c2, c3
FROM staging_table
LOG ERRORS INTO errlog ('some comment') REJECT LIMIT UNLIMITED;
Ensuite, toutes les lignes qui auraient généré une erreur sont disponibles dans la table errlog
. Vous devez créer cette table errlog
(ou le nom de votre choix) manuellement avant d'exécuter l'insertion à l'aide de DBMS_ERRLOG.CREATE_ERROR_LOG
.
Voir le manuel pour plus de détails
Si vous êtes sur 11g, vous pouvez utiliser l'indice 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.
Je ne pense pas qu'il y en ait un, mais pour gagner du temps, vous pouvez tenter l'insertion et ignorer l'erreur inévitable:
begin
insert into table_a( col1, col2, col3 )
values ( 1, 2, 3 );
exception when dup_val_on_index then
null;
end;
/
Cela ignorera uniquement les exceptions générées spécifiquement par une clé primaire en double ou des contraintes de clé uniques; tout le reste sera soulevé comme d'habitude.
Si vous ne voulez pas faire cela, vous devez d'abord sélectionner dans le tableau, ce qui n'est pas vraiment efficace.
Une autre 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)
ou tu pourrais faire
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
Une solution simple
insert into t1
select from t2
where not exists
(select 1 from t1 where t1.id= t2.id)
encore un autre "où pas existe" -variant utilisant dual ...
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');
Celui-ci n'est pas le mien, mais s'est avéré très utile avec sqlloader:
créez une vue qui pointe vers votre table:
CREATE OR REPLACE VIEW test_view
AS SELECT * FROM test_tab
créer le déclencheur:
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;
et dans le fichier ctl, insérez plutôt dans la vue:
OPTIONS(ERRORS=0)
LOAD DATA
INFILE 'file_with_duplicates.csv'
INTO TABLE test_view
FIELDS TERMINATED BY ','
(id, field1)
Que diriez-vous simplement d'ajouter un index avec tous les champs dont vous avez besoin pour rechercher les dupes et dire qu'il doit être unique? Enregistre un contrôle de lecture.