Консультация № 168445
28.05.2009, 15:17
0.00 руб.
0 16 2
Здравствуйте!
Имеется 2 заполненные таблицы:
1. AUTO (gos_nom, models, и т.д.)
2. MODEL (model, vmestit и т.д.)
Таблицы связаны по полю models=model.
Мне необходимо узнать, какой модели нет в таблице MODEL, которая имеется в таблице AUTO и добавить недостающую модель в таблицу MODEL.
Помогите написать скрипт.

Обсуждение

Неизвестный
28.05.2009, 15:36
общий
это ответ
Здравствуйте, Orz.
SELECT * FROM AUTO as a WHERE NOT EXISTS (SELECT model FROM MODEL as m WHERE m.model = a.models)
5
Спасибо за ответ!
Неизвестный
28.05.2009, 15:36
общий
это ответ
Здравствуйте, Orz.
попробуйте так

insert into model(model) SELECT models FROM auto where models not in (select model from model);
5
Спасибо за ответ!
Неизвестный
28.05.2009, 15:44
общий
Во первых - слово AUTO есть зарезервированное во многих СУБД и его использование при именование объектов не допустимо.
Во вторых - а как Вы сделали связь по полю MODEL если не удовлетворены зависимости??? Связь как раз и предполагает контроль наличия данных с целью обеспечения их целостности. т.е. что бы эти данные были и были не противоречивы.
В третьих - крайне не рекомендуется использовать название поля одинаковым с названием таблицы - это так же чревато сложностями. К тому же, есть правило - таблицы это множественное число (много записей) и в Вашем случае, это может быть MODELS для имени таблицы.
Неизвестный
28.05.2009, 16:08
общий
чтоб в именах таблицы или поля использовать зарезервированое слово, его нужно брать в обратные кавычки `auto`. Связь по полю может и не сделана, может база не поддерживает внешние ключи. по поводу "крайне не рекомендуется использовать название поля одинаковым с названием таблицы - это так же чревато сложностями" согласен. "К тому же, есть правило - таблицы это множественное число (много записей) и в Вашем случае, это может быть MODELS для имени таблицы" тоже согласен. А так мой запрос поидее должен удовлетворить потребность вопроса.
Неизвестный
28.05.2009, 16:27
общий
чтоб в именах таблицы или поля использовать зарезервированое слово, его нужно брать в обратные кавычки `auto`.

Кто сказал?? Тут даже не упомянули с какой СУБД работают, MSSQL например такого не потерпит.
Неизвестный
28.05.2009, 16:30
общий
to Victor Pyrlik, BahuL
В моем вопросе я немного изменил названия таблиц и полей для удобства понимания.
Выводится ошибка:
Violation of PRIMARY KEY constraint 'PK_T_model'. Cannot insert duplicate key in object 'dbo.T_MODEL'.
значит такое значение в таблицу T_MODEL вносится дважды, что недопустимо.

MS SQL 2005

Неизвестный
28.05.2009, 16:30
общий
чтоб в именах таблицы или поля использовать зарезервированое слово, его нужно брать в обратные кавычки `auto`

это справедливо не для всех СУБД..
Насчет связей, скорее всего действительно, связь программная а не на уровне СУБД.
Неизвестный
28.05.2009, 16:33
общий
Orz:
для того, что бы не возникало такой ошибки используйте запрос что Вам дали, т.е.
Код:
INSERT INTO MODEL (MODEL) 
SELECT MODELS FROM AUTOM
WHERE MODELS NOT IN (SELECT MODEL FROM MODEL)

это гарантирует что будут выбраны только те записи, которых нет в таблице MODEL..
Неизвестный
28.05.2009, 16:35
общий
Вам нужно еще сгруппировать тогда, иначе Вы несколько раз вносите:
INSERT INTO model(model)
SELECT models FROM AUTO as a WHERE NOT EXISTS (SELECT model FROM MODEL as m WHERE m.model = a.models)
GROUP BY models
Неизвестный
28.05.2009, 16:40
общий
Цитата: 121537
Кто сказал?? Тут даже не упомянули с какой СУБД работают, MSSQL например такого не потерпит.

Виноват... Таки да. С разными СУБД разный синтаксис...

У меня на MySQL мой запрос ( insert into model(model) SELECT models FROM auto where models not in (select model from model) ) выполнился нормально, хотя возможно я не все возможные ошибки проверил
Неизвестный
28.05.2009, 16:42
общий
[q=121537][/q]
Вот сейчас все без ошибок добавилось. Спасибо.
Неизвестный
28.05.2009, 16:55
общий
Hubbitus:
SELECT models FROM AUTO as a WHERE NOT EXISTS (SELECT model FROM MODEL as m WHERE m.model = a.models)


перевожу на понятный язык:

ВЫБРАТЬ МОДЕЛИ ИЗ ТАБЛИЦЫ AOUTO
ЕСЛИ НЕ НАЙДЕНА НИ ОДНА ЗАПИСЬ ЗАПРОСА
(ВЫБРАТЬ МОДЕЛЬ ИЗ ТАБЛИЦЫ MOEDL ЕСЛИ ПОЛЕ MODEL ТАБЛИЦЫ MODEL РАВНО ПОЛЮ MODEL ТАБЛИЦЫ AUTO)

попробуйте проанализировать данный запрос..
Неизвестный
28.05.2009, 17:03
общий
ВЫБРАТЬ МОДЕЛИ ИЗ ТАБЛИЦЫ AOUTO
ЕСЛИ НЕ НАЙДЕНА НИ ОДНА ЗАПИСЬ ЗАПРОСА

Нет, Вы нее правы совершенно. RTFM. Такой запрос называется корреляционным (или коррелирующим), он выбирает записи из таблицы AUTO, если для данной строчки в таблице MODEL не сопоставлено по равенству полей model = models. Все остальные строки в результат не включаются.
Ну и в конце группировка, потому что таких строк может быть несколько, а нам нужно только одну вставить.
Неизвестный
28.05.2009, 17:16
общий
Hubbitus:
я просил проанализировать..
анализ можно было сделать относительно запроса
INSERT INTO MODEL (MODEL)
SELECT MODELS FROM AUTOM
WHERE MODELS NOT IN (SELECT MODEL FROM MODEL)
GROUP BY MODELS

тут:
1. делается выборка по условию отрицания совпадений
2. после этого, в цикле делается вставка всех отобранных значений.

В Вашем случае, сканирование идет по таблице AUTO.. А так как это продуктивная таблица, то затраты на порядки больше чем выборка из справочной таблицы. И при больших объемах это может отличаться от долей секунды при первом запросе до минут при Вашем запросе.. с остальными накладными сложностями.. вот и весь RTFM
Неизвестный
29.05.2009, 00:52
общий
Во-первых, ни о какой продуктивности и весах не было и речи. по ходу задачи не было ни слова сказано о количестве записей в одной или другой таблице.
Во-вторых, ох уж уж и вправду Вы говорили о неудобных и неправильных именах выбранных для полей и имен таблиц, раз 5 сейчас перечитывал условие, чтобы врубиться что же требовалось в точности...
Похоже Вы правы, порядок таблиц я перепутал, должно быть так:
Код:
INSERT INTO model(model) 
SELECT model FROM [MODEL] m WHERE NOT EXISTS (SELECT models FROM [AUTO] a WHERE m.model = a.models)
GROUP BY model


Использовать NOT EXISTS вместо NOT IN выборкой по полю все же предпочтительнее, как я полагаю, потому как оптимизация - поиск идет до первого обнаружения необходимого элемента, а не всех. Более того, все не возвращаются из подзапроса, особенно это будет заметно на больших таблицах и текстовых ключах, как в этом примере.
Неизвестный
29.05.2009, 01:06
общий
Hubbitus:
Во-первых, ни о какой продуктивности и весах не было и речи. по ходу задачи не было ни слова сказано о количестве записей в одной или другой таблице.

Вы правы.. моё дополнение в части Вашего запроса было излишним.
Форма ответа