2011-12-15 16 views
7

Tengo 3 tablas: dentistas, grupos y groupdentlink. Muchos dentistas se vinculan a muchos grupos a través de la tabla groupdentlink.Insertar donde no existe-Sin clave principal

Estoy tratando de hacer una consulta donde inserte filas en groupdentlink (vinculando a todos los dentistas en el estado con todos los grupos en el estado) pero solo si esas filas no existen. En pocas palabras, quiero agregar nuevas filas sin sobreescribir las existentes o duplicarlas.

Así que la intención de la consulta es algo así como:

INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) 
VALUES ('$_POST[id]', '$groupid', '$scheduleid') 
WHERE NOT EXISTS ('$_POST[id]', '$groupid') 

Y no tengo ninguna clave primaria en la tabla groupdentlink.

¡Gracias de antemano!

Respuesta

18

Si realmente quiere escribir su propia consulta (de trabajo) ..


INSERT INTO groupdentlink (
    f_dent_id, f_group_id, f_schedule_id 
) SELECT 
    '$_POST[id]' f_dent_id, 
    '$groupid' f_group_id, 
    '$scheduleid' f_schedule_id 
FROM DUAL 
WHERE NOT EXISTS (
    SELECT 1 
    FROM `groupdentlink` 
    WHERE 
    f_dent_id = '$_POST[id]' AND f_group_id = '$groupid' 
    LIMIT 1 -- will stop mysql to stop searching after first match 
) 

... pero MySQL puede manejar todo esto para usted!


No es necesario claves primarias que MySQL manejar esto para usted, usted debe agregar una restricción de clave UNIQUE en el conjunto combinado de las dos columnas.

Consulta para agregar la clave única dent_group_uniq_key a groupdentlink.

ALTER TABLE groupdentlink ADD UNIQUE KEY `dent_group_uniq_key` (
    f_dent_id, f_group_id 
); 

A continuación, utilice INSERT IGNORE en su consulta:

INSERT IGNORE INTO groupdentlink (
    f_dent_id, f_group_id, f_schedule_id 
) VALUES (
    '$_POST[id]', '$groupid', '$scheduleid' 
) 

INSERT IGNORE intentará insertar una fila a la tabla, si falla debido a una restricción de clave que va a actuar como si nada ocurrirá.

+0

OK, pero no obtendrá un error si falla por diferentes motivos, como una violación de restricción de clave externa. – greyfairer

+0

@greyfairer Solo se "IGNORARÁ" si la inserción falla debido a una clave duplicada, aún se aplican restricciones de clave externa. –

+0

Muchas gracias. Estoy usando el segundo método: clave única de columnas combinadas, ya que me parece más simple. –

2

¡Ya casi lo tienes! Puede usar una instrucción select para alimentar una instrucción de inserción. Sólo hacer esto:

INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) 
SELECT '$_POST[id]', '$groupid', '$scheduleid' 
WHERE 
    NOT EXISTS (
    select 
     1 
    from 
     groupdentlink 
    where 
     f_dent_id = $_POST[id] 
     and f_group_id = '$groupid' 
    ) 
+0

hmm. Aquí está mi pregunta: "INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) \t SELECT '$ _POST [id]', '$ ROWV [id]', '$ fila [f_sched_id]' \t DONDE \t NO EXISTE ( \t SELECCIONAR 1 dE groupdentlink DONDE f_dent_id = '$ _POST [id]' y f_group_id = '$ groupid'" ... y yo estoy recibiendo un error de sintaxis –

+0

necesita los paréntesis de cierre en la cláusula existe. – Eric

+0

... corrigió eso. Todavía no funciona. Oy :( –

4
INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) 
SELECT '$_POST[id]', '$groupid', '$scheduleid' FROM dual 
WHERE NOT EXISTS (
    select * from groupdentlink 
    where f_dent_id='$_POST[id]' 
    and f_group_id='$groupid' 
) 

Y creo que se puede crear una clave principal compuesta de la combinación (f_dent_id, f_group_id) sólo para asegurarse.

+0

Como sugerencia, use '1' en lugar de' * 'en sus sentencias' exists' para que no intente extraer un gran conjunto de columnas en la memoria. Acelera un poco la consulta (puede tener un gran impacto cuanto más grande sea la consulta, y depende del motor). – Eric

+0

@Eric, ese no es el caso. Consulte [Docs] (http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html): Tradicionalmente, una subconsulta EXISTS comienza con SELECT *, pero podría Comience con SELECCIONAR 5 o SELECCIONAR columna1 o cualquier cosa. MySQL ignora la lista SELECT en dicha subconsulta, por lo que no hace diferencia. –

+0

Ah, MySQL no hace eso, las versiones anteriores de SQL Server solían (no sé si todavía lo hacen), y ahí es donde todo mi trabajo está hecho. Lo uso como una práctica recomendada. – Eric

1
INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) 
VALUES ('$_POST[id]', '$groupid', '$scheduleid') 
WHERE NOT EXISTS (
    select * from groupdentlink 
    where f_dent_id='$_POST[id]' 
    and f_group_id='$groupid' 
) 

y creo que se puede crear una clave principal compuesta de la combinación (f_dent_id, f_group_id).

Cuestiones relacionadas