2010-02-01 12 views
6

que realiza una inserción de la siguiente manera:ignorar inserción de filas que infringen índice de clave duplicada

INSERT INTO foo (a,b,c) 
    SELECT x,y,z 
    FROM fubar 
    WHERE ... 

Sin embargo, si algunas de las filas que se están insertando violan el índice de clave duplicada en foo, quiero que la base de datos para ignore esas filas, y no las inserte y continúe insertando las otras filas.

El DB en cuestión es Informix 11.5. Actualmente todo lo que sucede es que el DB está lanzando una excepción. Si trato de manejar la excepción con:

ON EXCEPTION IN (-239) 
END EXCEPTION WITH RESUME; 

... no ayuda porque después se detecta la excepción, todo el inserto se salta.

No creo que informix admita INSERT IGNORE, o INSERTAR ... EN LLAVE DUPLICADA ..., pero puede corregirme si me equivoco.

+0

¿Soporta Informix uniones a la izquierda? Si es así, simplemente no puede consultar las filas que ya están en foo. –

+1

Informix es compatible con LEFT JOIN. También (IDS 11.50) es compatible con MERGE, que se puede utilizar para INSERTAR filas nuevas o ACTUALIZAR filas existentes. –

+0

¿Me estoy perdiendo algo aquí? ¿Por qué el índice es único? Me parece que esta pregunta debe cambiarse a "¿Cómo creo un índice no único en Informix?" –

Respuesta

5

Utilice la instrucción IF y la función EXISTS para verificar los registros existentes. O es probable que pueda incluir la función que existe en la cláusula WHERE, como a continuación

INSERT INTO foo (a,b,c) 
SELECT x,y,z 
FROM fubar 
WHERE (NOT EXISTS(SELECT a FROM foo WHERE ...)) 
+0

Esto solo es útil para evitar la duplicación de las filas originales en la tabla 'foo'. Si hay filas duplicadas en la tabla 'fubar', todavía se genera una excepción, porque la tabla' foo' en la instrucción 'NOT EXISTS (SELECT a FROM foo WHERE ...)' no contiene ninguna nueva fila en 'fubar' tabla hasta que se complete la operación 'INSERT '. – Rockallite

0

No sé acerca de Informix, pero con SQL Server, puede crear un índice, que sea único y luego establecer una propiedad de tener ignora las claves duplicadas para que no se genere ningún error en un duplicado. Simplemente es ignorado. Quizás Informix tiene algo similar.

2

Dependiendo de si desea conocer todos los errores (generalmente como resultado de una operación de carga de datos), considere usar violations tables.

START VIOLATIONS TABLE FOR foo; 

Esto creará un par de mesas y foo_vio foo_dia que contienen información acerca de filas que infringen las restricciones de integridad en la mesa.

Cuando has tenido suficiente, utilizar:

STOP VIOLATIONS TABLE FOR foo; 

Puede limpiar las tablas de diagnóstico en su tiempo libre. Hay campanas y silbidos en el comando para controlar qué tabla se utiliza, etc. (Tal vez debería tener en cuenta que esto supone que está utilizando IDS (IBM Informix Dynamic Server) y no, por ejemplo, Informix SE o Informix OnLine.)

Las tablas de violaciones son una opción para trabajos pesados, adecuada para cargas y similares. Normalmente no se utilizan para proteger SQL corrientes. Para eso, el INSERT protegido (con SELECT y DONDE NO EXISTE) es bastante efectivo: requiere que los datos ya estén en una tabla, pero las tablas temporales son fáciles de crear.

2

Hay un par de otras opciones a considerar.

A partir de la versión 11.50, Informix admite la instrucción MERGE. Esto podría usarse para insertar filas de fubar donde la fila correspondiente en foo no existe, y para actualizar las filas en foo con los valores de fubar donde la fila correspondiente ya existe en foo (el problema de la clave duplicada).

Otra forma de verlo es:

SELECT fubar.* 
    FROM fubar JOIN foo ON fubar.pk = foo.pk 
    INTO TEMP duplicate_entries; 

DELETE FROM fubar WHERE pk IN (SELECT pk FROM duplicate_entries); 

INSERT INTO foo SELECT * FROM fubar; 

...processs duplicate_entries 

DROP TABLE duplicate_entries 

Esto limpia la tabla de origen (fubar) de las entradas duplicadas (asumiendo que es sólo la clave primaria que se duplica) antes de tratar de insertar los datos.La tabla duplicate_entries contiene las filas en fubar con las claves duplicadas, las que necesitan un procesamiento especial en alguna forma o forma. O simplemente puede eliminar e ignorar esas filas, aunque, en mi experiencia, rara vez es una buena idea.

1

Grupo por tal vez su amigo en esto. Para evitar que se ingresen filas duplicadas. Use group by en su selección. Esto forzará los duplicados en una fila única. Lo único que haría es probar para ver si hay problemas de rendimiento. Además, asegúrese de incluir todas las filas que desea que sean únicas en el grupo o excluya las filas que no sean duplicadas.

INSERT INTO FOO(Name, Address, Age, Gadget, Price) 
select Name, Age, Gadget, Price 
from foobar 
group by Name, Age, Gadget, Price 

Donde nombre, edad, Gadget, Precio forman el índice de clave principal (o el índice de clave única). La otra posibilidad es escribir las filas duplicadas en una tabla de errores sin el índice y luego resolver los duplicados antes de insertarlos en la nueva tabla. Solo necesita agregar una cláusula count (*)> 1 a la anterior.

+0

Debería haber mirado la fecha en que se publicó. Sin embargo, si alguien necesita hacer algo similar, el código anterior es ANSI SQL, por lo que debería funcionar con cualquier RDBMS. – alaniane

Cuestiones relacionadas