2011-12-15 4 views
7

У меня есть 3 стола: стоматологи, группы и groupdentlink. Многие стоматологи связываются со многими группами через таблицу groupdentlink.Вставить, где не существует - без первичного ключа

Так что я пытаюсь сделать запрос, в котором он будет вставлять строки в groupdentlink (связывание всех дантистов в состоянии со всеми группами в состоянии), но только если эти строки еще не существуют. В двух словах я хочу добавить новые строки, не перезаписывая существующие или не дублируя их.

Так намерение запроса что-то вроде:

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

И у меня нет никаких первичных ключей в таблице groupdentlink.

Спасибо заранее!

ответ

18

Если вы действительно хотите, чтобы написать свой собственный (рабочий) запрос ..


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 
) 

... но MySQL может обрабатывать все это для вас!


Вам не нужны первичные ключи, чтобы сделать MySQL справиться с этим для вас, вы должны добавить UNIQUE ключевое ограничение на комбинированный набор из двух столбцов.

Запрос, чтобы добавить уникальный ключ dent_group_uniq_key в groupdentlink.

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

Затем используйте INSERT IGNORE по Вашему запросу:

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

INSERT IGNORE попытается вставить строку в таблицу, если она не сможет из-за ключа ограничения будет действовать, как будто ничего случиться.

+0

OK, но вы не получите сообщение об ошибке, если оно не по каким-либо причинам, как нарушение ограничения внешнего ключа. – greyfairer

+0

@greyfairer Он будет только «IGNORE», если вставка завершится неудачно из-за дублирования ключа, ограничения по внешним ключам все еще применяются. –

+0

Большое спасибо. Я использую второй метод: уникальный ключ из комбинированных столбцов, поскольку мне кажется, что он проще. –

2

У вас его почти нет! Вы можете использовать оператор select для подачи инструкции insert. Просто сделайте это:

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. Вот мой запрос: «INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) \t SELECT '$ _POST [ID]', '$ rowv [ID]', '$ строки [f_sched_id] \t ГДЕ \t НЕ СУЩЕСТВУЕТ ( \t ВЫБРАТЬ 1 FROM groupdentlink WHERE f_dent_id = '$ _POST [ID] и f_group_id =' $ GroupID» ... и я получаю ошибку синтаксиса –

+0

Вам нужно закрывающие скобка на такое положение. – Eric

+0

... исправлено это. Все еще не работает 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' 
) 

И я думаю, что вы можете создать составной первичный ключ комбинации (f_dent_id, f_group_id), просто чтобы убедиться.

+0

В качестве подсказки используйте '1' вместо' * 'для операторов' exist', чтобы вы не пытались отменить большой набор колонок в памяти. Ускоряет запрос немного (может иметь большое влияние, чем больше запрос получает, и зависит от движка). – Eric

+0

@ Эрик, это не так. См. [Документы] (http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html). Традиционно подзапрос EXISTS начинается с SELECT *, но он может начните с SELECT 5 или SELECT column1 или вообще ничего. MySQL игнорирует список SELECT в таком подзапросе, поэтому он не имеет значения. –

+0

Ах, MySQL этого не делает - более старые версии SQL Server, используемые (не знаю, продолжают ли они это делать), и именно там вся моя работа выполнена. Я использую ее как наилучшую практику. – 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' 
) 

И я думаю, что вы можете создать составной первичный ключ комбинации (f_dent_id, f_group_id).

Смежные вопросы