2011-12-15 22 views
7

Ho 3 tabelle: dentisti, gruppi e groupdentlink. Molti dentisti collegano a molti gruppi attraverso la tabella groupdentlink.Inserisci dove non esiste, senza chiave primaria

Quindi sto cercando di fare una query in cui inserirà le righe in groupdentlink (collegando tutti i dentisti nello stato con tutti i gruppi nello stato) ma solo se tali file non esistono già. In poche parole voglio aggiungere nuove righe senza sovrascrivere quelle esistenti o duplicarle.

Così il intento della query è qualcosa di simile:

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

E non avere chiavi primarie nella tabella groupdentlink.

Grazie in anticipo!

risposta

18

Se davvero si vuole scrivere il proprio (di lavoro) di query ..


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 
) 

... ma MySQL può gestire tutto questo per voi!


Non è necessario chiavi primarie per rendere MySQL gestire questo per voi, si dovrebbe aggiungere un vincolo di chiave UNIQUE sul set combinato delle due colonne.

Interrogazione per aggiungere la chiave univoca dent_group_uniq_key a groupdentlink.

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

Quindi utilizzare INSERT IGNORE sulla vostra richiesta:

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

INSERT IGNORE cercherà di inserire una riga al vostro tavolo, se non riesce a causa di un vincolo di chiave si comporterà come se niente accada.

+0

OK, ma non si otterrà un errore se non riesce per motivi diversi, come una violazione del vincolo di chiave esterna. – greyfairer

+0

@greyfairer Sarà "IGNORE" solo se l'inserimento non riesce a causa di una chiave duplicata, i vincoli di chiave esterna si applicano ancora. –

+0

Grazie mille. Sto usando il secondo metodo: chiave unica da colonne combinate poiché mi sembra più semplice. –

2

Hai quasi capito! È possibile utilizzare un'istruzione select per alimentare un'istruzione insert. Basta fare questo:

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. Ecco la mia domanda: "INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) \t SELEZIONA '$ _POST [id]', '$ rowv [id]', '$ row [f_sched_id]' \t DOVE \t NON ESISTE ( \t SELECT 1 FROM WHERE groupdentlink f_dent_id = '$ _POST [id]' e f_group_id = '$ groupid'" ... e sto ottenendo un errore di sintassi –

+0

È necessario la parentesi di chiusura sulla esiste clausola. – Eric

+0

... risolto. Ancora non funziona 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' 
) 

E penso che è possibile creare una chiave primaria composta dalla combinazione (f_dent_id, f_group_id) solo per assicurarsi.

+0

Come suggerimento, usa '1' invece di' * 'sulle tue istruzioni' exists' in modo che tu non stia cercando di richiamare un grande set di colonne in memoria. Accelera un po 'la query (può avere un grande impatto più grande diventa la query e dipende dal motore). – Eric

+0

@Eric, non è questo il caso. Vedi [Docs] (http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html): Tradizionalmente, una subquery EXISTS inizia con SELECT *, ma potrebbe iniziare con SELECT 5 o SELECT column1 o nulla del tutto. MySQL ignora l'elenco SELECT in tale subquery, quindi non fa alcuna differenza. –

+0

Ah, MySQL non lo fa - le versioni precedenti di SQL Server erano abituate a (non so se lo fanno ancora), ed è lì che tutto il mio lavoro è terminato. Lo uso come best practice. – 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' 
) 

e penso che è possibile creare una chiave primaria composta dalla combinazione (f_dent_id, f_group_id).