Я бы порекомендовал использовать INSERT...ON DUPLICATE KEY UPDATE
.
Если вы используете INSERT IGNORE
, то строка фактически не будет вставлена, если она приведет к дублированию ключа. Но утверждение не приведет к ошибке. Вместо этого он генерирует предупреждение. Эти случаи включают в себя:
- Вставка дубликата ключа в столбцы с
PRIMARY KEY
или UNIQUE
ограничениями.
- Вставка NULL в столбец с
NOT NULL
ограничением.
- Вставка строки в многораздельную таблицу, но вставляемые значения не отображаются на раздел.
Если вы используете REPLACE
, MySQL фактически DELETE
следует за INSERT
внутренним, что имеет некоторые неожиданные побочные эффекты:
- Новый идентификатор автоинкремента назначен.
- Зависимые строки с внешними ключами могут быть удалены (если вы используете каскадные внешние ключи), либо можете запретить
REPLACE
.
- Триггеры, которые запускаются,
DELETE
выполняются без необходимости.
- Побочные эффекты распространяются и на реплики.
исправление: оба REPLACE
и INSERT...ON DUPLICATE KEY UPDATE
являются нестандартными, проприетарными изобретениями, специфичными для MySQL. ANSI SQL 2003 определяет MERGE
оператор, который может удовлетворить ту же потребность (и более), но MySQL не поддерживает MERGE
оператор.
Пользователь попытался отредактировать это сообщение (редактирование было отклонено). При редактировании была предпринята попытка добавить утверждение, которое INSERT...ON DUPLICATE KEY UPDATE
приводит к назначению нового идентификатора автоинкремента. Это правда, что новый идентификатор генерируется , но он не используется в измененной строке.
См. Демонстрацию ниже, протестированную с Percona Server 5.5.28. Переменная конфигурации innodb_autoinc_lock_mode=1
(по умолчанию):
mysql> create table foo (id serial primary key, u int, unique key (u));
mysql> insert into foo (u) values (10);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 10 |
+----+------+
mysql> show create table foo\G
CREATE TABLE `foo` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`u` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u` (`u`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
mysql> insert into foo (u) values (10) on duplicate key update u = 20;
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> show create table foo\G
CREATE TABLE `foo` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`u` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u` (`u`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
Выше показано, что оператор IODKU обнаруживает дубликат и вызывает обновление, чтобы изменить значение u
. Обратите внимание, что AUTO_INCREMENT=3
указывает, что идентификатор был создан, но не используется в строке.
Принимая во внимание, REPLACE
что удаляет исходную строку и вставляет новую строку, генерируя и сохраняя новый идентификатор автоинкремента:
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 3 | 20 |
+----+------+
INSERT ... ON DUPLICATE KEY UPDATE ...
утверждений. Большая часть данных является дубликатом, и это привело к тому, что один случай ИИ ПК увеличился с 17 029 941 до 46 461 740 между двумя строками. Это поколение нового ИИ каждый раз означает, что ваш диапазон может быть очень быстро заполнен, и вам нужно вычистить. Этому столу всего две недели!В случае, если вы хотите увидеть, что все это значит, вот пошагово все:
Первичный ключ основан на обоих столбцах этой краткой справочной таблицы. Первичный ключ требует уникальных значений.
Давайте начнем:
обратите внимание, что выше сэкономлено слишком много дополнительной работы, установив столбец, равный самому себе, обновление не требуется
а теперь несколько тестов строк:
в консоли не было сгенерировано никаких других сообщений, и теперь у них есть эти 4 значения в данных таблицы. Я удалил все, кроме (1,1), чтобы я мог тестировать с того же игрового поля
Так что у вас есть это. Поскольку все это было выполнено на свежем столе почти без данных и не в производстве, время выполнения было микроскопическим и не имело значения. Любой, у кого есть реальные данные, будет рад предоставить их.
источник
INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
.Что-то важное, что нужно добавить: при использовании INSERT IGNORE, когда у вас есть ключевые нарушения, MySQL НЕ выдает предупреждение!
Например, если вы попытаетесь вставить 100 записей за раз, причем одна неисправная, вы попадете в интерактивный режим:
Как видите: предупреждений нет! Это поведение даже неправильно описано в официальной документации Mysql.
Если ваш скрипт должен быть проинформирован, если некоторые записи не были добавлены (из-за нарушения ключа), вы должны вызвать mysql_info () и проанализировать его для значения «Duplicates».
источник
mysqli_affected_rows()
будет узнать,INSERT
действительно ли это произошло.Cannot add or update a child row: a foreign key constraint fails
и ни одной строки (даже годные) не добавляются.INSERT IGNORE
дубликаты ключей игнорируются без ошибок или предупреждений.Я обычно использую
INSERT IGNORE
, и это звучит точно так же, как вы ищете. Пока вы знаете, что строки, которые могут вызвать конфликты индексов, вставляться не будут, и вы планируете свою программу соответствующим образом, это не должно вызывать никаких проблем.источник
Я знаю, что это старая версия, но я добавлю эту заметку на случай, если кто-то другой (например, я) попадет на эту страницу, пытаясь найти информацию на INSERT..IGNORE.
Как упоминалось выше, если вы используете INSERT..IGNORE, ошибки, возникающие при выполнении оператора INSERT, обрабатываются как предупреждения.
Одна вещь, которая явно не упоминается, заключается в том, что INSERT..IGNORE приведет к тому, что недопустимые значения будут корректироваться до ближайших значений при вставке (тогда как недопустимые значения приводят к прерыванию запроса, если ключевое слово IGNORE не использовалось).
источник
ON DUPLICATE KEY UPDATE на самом деле не в стандарте. Это примерно так же стандартно, как REPLACE. Смотрите SQL MERGE .
По сути, обе команды являются альтернативно-синтаксическими версиями стандартных команд.
источник
Replace
В кажется, как вариант. Или вы можете проверить сЭто будет вставить или удалить, а затем вставить. Я склонен идти на
IF NOT EXISTS
проверку первым.источник
REPLACE
удаляет все строки в таблице, соответствующие любомуPRIMARY
илиUNIQUE
ключу, затемINSERTs
. Это потенциально намного больше работы, чем IODKU.Потенциальная опасность INSERT IGNORE. Если вы пытаетесь вставить значение VARCHAR дольше, чем столбец был определен с - значение будет усечено и вставлено ДАЖЕ ЕСЛИ строгий режим включен.
источник
При использовании
insert ignore
имеющимSHOW WARNINGS;
заявление в конце вашего набора запроса покажет таблицу со всеми предупреждениями, в том числе , какие идентификаторы были дубликаты.источник
SHOW WARNINGS;
только кажется, влияет на последний запрос. Любые предыдущие утверждения не накапливаются, если у вас есть более одного утверждения.Если вы хотите вставить в таблицу и при конфликте первичного ключа или уникального индекса, он обновит конфликтующую строку вместо вставки этой строки.
Синтаксис:
Теперь здесь этот оператор вставки может выглядеть иначе, чем вы видели ранее. Этот оператор вставки пытается вставить строку в table1 со значениями a и b в столбцы column1 и column2 соответственно.
Давайте разберемся в этом утверждении подробно:
Например: здесь column1 определяется как первичный ключ в table1.
Теперь, если в таблице1 нет строки, имеющей значение «a» в column1. Таким образом, этот оператор вставит строку в таблицу1.
Теперь, если в таблице 1 есть строка, имеющая значение «a» в столбце 2. Таким образом, этот оператор обновит значение столбца в строке на «с», где значение столбца на «а».
Поэтому, если вы хотите вставить новую строку, обновите эту строку в случае конфликта первичного ключа или уникального индекса.
Подробнее по этой ссылке
источник
INSERT...ON DUPLICATE KEY UPDATE
предпочтительнее для предотвращения непредвиденных исключений управления.Это решение работает, когда у вас ** 1 уникальное ограничение **
В моем случае я знаю это
col1
иcol2
делаю уникальный составной индекс.Он отслеживает ошибку, но не создает исключение для дубликата. Что касается производительности, обновление с тем же значением является эффективным, так как MySQL замечает это и не обновляет его
Идея использовать этот подход возникла в комментариях на phpdelusion.net/pdo .
источник