Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.191.186.72] |
|
Данный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных - обсуждаем в разделе "Базы данных: общие вопросы". Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ. |
Сообщ.
#1
,
|
|||||||||||||||||
|
Имеется таблица foo, типа
Существует ли такой функционал типа INSERT INTO foo (id, bar1, bar2, bar3) VALUES (NULL, 12, 29, 'ololo') WHERE bar1<>12 AND bar2<>29 |
Сообщ.
#2
,
|
|
|
Есть
INSERT INTO foo (id, bar1, bar2, bar3) select id, bar1, bar2, bar3 from foo where bar1<>12 AND bar2<>29 Есть еще merge но это зависит от диалекта sql. |
Сообщ.
#3
,
|
|
|
Ммм, если я правильно понимаю, то будут добавлены уже существующие значения, а мне надо новые, мной указанные. И добавить их в таблицу, если их ещё нет.
|
Сообщ.
#4
,
|
|
|
Может проще процедуру написать?
Добавлено Цитата Gonarh @ а мне надо новые, мной указанные Для этого и придумана INSERT INTO ... VALUES , sql не знает что вы хотите добавить данные должны где-то быть. Но проверку перед добавлением можно сделать. |
Сообщ.
#5
,
|
|
|
Мне нужно было просто знать, позволяет ли язык такое или нет, буду пилить проверку в другом месте. Спасибо. Тему закрываю.
|
Сообщ.
#6
,
|
|
|
Цитата Gonarh @ позволяет ли язык такое или нет нет. |
Сообщ.
#7
,
|
|||||||||||||||||
|
Цитата Gonarh @ Имеется таблица foo, типа
Существует ли такой функционал типа INSERT INTO foo (id, bar1, bar2, bar3) VALUES (NULL, 12, 29, 'ololo') WHERE bar1<>12 AND bar2<>29 сначало проверить через SELECT а потом добавлять или не добавлять через INSERT, так делают правильные чуваки такие как я |
Сообщ.
#8
,
|
|
|
Цитата Gonarh @ Существует ли такой функционал типа INSERT INTO foo (id, bar1, bar2, bar3) VALUES (NULL, 12, 29, 'ololo') WHERE bar1<>12 AND bar2<>29 Синтаксис INSERT .. VALUES в принципе не предусматривает наличия секции WHERE. Цитата Gonarh @ будут добавлены уже существующие значения, а мне надо новые, мной указанные. И добавить их в таблицу, если их ещё нет. Этими проблемами должен заниматься не запрос, а подсистема контроля. Для работы которой создаётся уникальный индекс по полю, совокупности полей либо ограчение (constraint) по выражению, не позволяющие вставить в таблицу дубликат существующей записи. Либо, если индекс не оправдывается по каким-то соображениям, создаются костыли - в простейшем варианте триггеры, в более сложном логика выносится в хранимые процедуры. Однако следует понимать, что при использовании таких костылей всегда есть обходные пути, позволяющие внести в таблицу противоречащие логике данные. Цитата Cfon @ сначало проверить через SELECT а потом добавлять или не добавлять через INSERT, так делают правильные чуваки Правильные - используют для этого встроенные средства альтернативной обработки в случае нарушения требования уникальности, которые есть практически в любом диалекте. Merge, Insert .. on Duplicate Key Update и т.п. А делать руками то, что умеет сервер (и умеет, кстати, лучше, чем клиент)... ну костыль он костыль и есть, сиди, трясись и жди, когда сломается. |
Сообщ.
#9
,
|
|
|
Цитата Akina @ Для работы которой создаётся уникальный индекс по совокупности полей не позволяющий вставить в таблицу дубликат существующей записи О, спасибо, не подумал. |
Сообщ.
#10
,
|
|
|
ну и сиди там с альтернативой, а я буду правильно делать!
диалект мля |
Сообщ.
#11
,
|
|
|
Индексы! Гениально!
INSERT INTO `ololo`.`foo` ( `id` , `bar3` , `bar2` , `bar1` ) VALUES ( NULL , NULL , '2', '2' ) Ответ MySQL: Документация #1062 - Duplicate entry '2-2' for key 'test' Сколько же у меня говнокода можно убрать Добавлено Цитата Cfon @ сначало проверить через SELECT а потом добавлять или не добавлять через INSERT, так делают правильные чуваки такие как я Я добавляю блоками по 20-30к записей, это чо, мне столько селектов делать? Ебанулся? |
Сообщ.
#12
,
|
|
|
Цитата Gonarh @ cуществует ли такой функционал типа INSERT INTO foo (id, bar1, bar2, bar3) VALUES (NULL, 12, 29, 'ololo') WHERE bar1<>12 AND bar2<>29 Сообщение отредактировано: Gonarh - Сегодня, 07:37 insert into ...... where not exists(select 1 from foo where bar1 = 12 and bar2 = 29) Добавлено Цитата Gonarh @ Индексы! Гениально! Индекс нужен обязательно, но лучше бы, чтоб insert не выдавал ошибок без необходимости |
Сообщ.
#13
,
|
|
|
Цитата Gonarh @ Я добавляю блоками по 20-30к записей Учти, что при нарушении требования уникальности хотя бы для одной записи ни одна запись не будет вставлена - в т.ч. и те, которые требования уникальности не нарушают. Чтобы не-дубликаты вставились, нужно использовать merge-варианты запроса на добавление. Для MySQL это обычно дополнительная секция INSERT INTO ... VALUES ... ON DUPLICATE KEY UPDATE id = id; В таком варианте все не-дубликаты вставляются, а дубликаты просто игнорируются (поскольку изменения данных не происходит, секция отрабатывается формально и не приводит к реальному обновлению данных теми же значениями). Можно, конечно, использовать и упрощённую версию - INSERT IGNORE, но на последних версиях она может вступать в противоречие с текущими настройками сервера, что заставит менять настройки соединения, а это нехорошо. |
Сообщ.
#14
,
|
|
|
Цитата Gonarh @ Я добавляю блоками по 20-30к записей, это чо, мне столько селектов делать? Ебанулся? ошалел да? Добавлено ща я у ся в демо покажу как надо инсертить! |
Сообщ.
#15
,
|
|
|
Цитата Олег М @ insert into ...... where not exists Оно, конечно, тоже вариант... но когда формальных ограничений (уникальных индексов) несколько, запрос начнёт пухнуть. Причём быстро - ведь ту же совокупность параметров придётся указывать литерально и в INSERT, и в каждом NOT EXISTS (или в каждом его WHERE). Ну и опять же - дополнительный, в общем ненужный, запрос. Да и обновление пойдёт фиг знает в каком порядке, поскольку все списки - и существующих записей, и добавляемых,- пересортируются для эффективного выполнения предыдущих этапов... |
Сообщ.
#16
,
|
|
|
Цитата Akina @ Оно, конечно, тоже вариант... но когда формальных ограничений (уникальных индексов) несколько, запрос начнёт пухнуть. Причём быстро - ведь ту же совокупность параметров придётся указывать литерально и в INSERT, и в каждом NOT EXISTS (или в каждом его WHERE). Ну и опять же - дополнительный, в общем ненужный, запрос. Да и обновление пойдёт фиг знает в каком порядке, поскольку все списки - и существующих записей, и добавляемых,- пересортируются для эффективного выполнения предыдущих этапов... Тут выбор невелик - либо проверять уникальные значения, либо получать ошибку. Я показал простейший вариант, причём не самый плохой. |
Сообщ.
#17
,
|
|
|
а речь о пакетной вставке тогда ИМХО лучше сначала сравнить нет ли в таргет-таблице дубликатов, а потом инсертить без задержек на проверку.
делаем SELECTs запоминаем ids тех что уже есть, далее инсертим того что еще нет, гениально не правда ли? |
Сообщ.
#18
,
|
|
|
Цитата Cfon @ а речь о пакетной вставке тогда ИМХО лучше сначала сравнить нет ли в таргет-таблице дубликатов, а потом инсертить без задержек на проверку. Тебе в любом случае придётся проверять каждую строку в пакете. И делать это именно в insert'e. Там можно сделать через join, но не уверен, что это что-то улучшит Добавлено Цитата Cfon @ делаем SELECTs запоминаем ids тех что уже есть, далее инсертим того что еще нет, гениально не правда ли? Ну да, скопировать пол-таблицы - это действительно гениальное решение |
Сообщ.
#19
,
|
|
|
Цитата Олег М @ Цитата Cfon @ делаем SELECTs запоминаем ids тех что уже есть, далее инсертим того что еще нет, гениально не правда ли? Ну да, скопировать пол-таблицы - это действительно гениальное решение нет я имел ввиду запомнить тока ids, но конечно стоит протестить. |
Сообщ.
#20
,
|
|
|
Цитата Олег М @ Тебе в любом случае придётся проверять каждую строку в пакете. И делать это именно в insert'e. Там можно сделать через join, но не уверен, что это что-то улучшит Я же указал два варианта решения. И оба - лучше, чем JOIN, как по ресам, так и по скорости. К тому же JOIN практически неприменим, если вставка идёт не из другой таблицы, а из списка (INSERT .. VALUES и т.п.). |
Сообщ.
#21
,
|
|
|
Цитата Cfon @ а речь о пакетной вставке тогда ИМХО лучше сначала сравнить нет ли в таргет-таблице дубликатов, а потом инсертить без задержек на проверку. делаем SELECTs запоминаем ids тех что уже есть, далее инсертим того что еще нет, гениально не правда ли? Зачем "изобретать велосипед" когда merge это уже делает без труда. |
Сообщ.
#22
,
|
|
|
Цитата Bas @ Зачем "изобретать велосипед" когда merge это уже делает без труда. как насчет пакетной вставки он нормуль? если да то пускай будет |
Сообщ.
#23
,
|
|
|
Цитата Bas @ Зачем "изобретать велосипед" когда merge это уже делает без труда. Ну если учесть, что у ТС имеет место быть MySQL, то MERGE слегка не в кассу. |
Сообщ.
#24
,
|
|
|
Спасибо за помощь и разъяснения.
|