& ldquo; INSERT IGNORE & rdquo; vs & ldquo; INSERT & hellip; ОБНОВЛЕНИЕ КЛЮЧЕВЫХ КЛЮЧЕЙ & rdquo;

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

  • ON DUPLICATE KEY UPDATE, что подразумевает ненужное обновление при некоторой стоимости, либо
  • INSERT IGNORE, что подразумевает приглашение на другие виды неспособности проскользнуть без предупреждения.

Прав ли я в этих предположениях? Как лучше всего пропустить строки, которые могут вызвать дублирование, и просто перейти к другим строкам?

819
задан 17.05.2020, 07:04

4 ответа

Я рекомендовал бы использовать INSERT...ON DUPLICATE KEY UPDATE.

, Если Вы используете INSERT IGNORE, затем строка не будет на самом деле вставлена, если она приведет к дублирующемуся ключу. Но оператор не генерирует ошибку. Это генерирует предупреждение вместо этого. Эти случаи включают:

  • Вставка дублирующегося ключа в столбцах с PRIMARY KEY или UNIQUE ограничения.
  • Вставка ПУСТОГО УКАЗАТЕЛЯ в столбец с NOT NULL ограничение.
  • Вставка строки к разделенной таблице, но значений, которые Вы вставляете, не отображается на раздел.

, Если Вы используете REPLACE, MySQL на самом деле делает DELETE сопровождаемый INSERT внутренне, который имеет некоторые неожиданные побочные эффекты:

  • А новый автоинкрементный идентификатор выделяется.
  • Зависимые строки с внешними ключами могут быть удалены (если Вы используете каскадные внешние ключи), или иначе предотвратите REPLACE.
  • Триггеры, которые стреляют DELETE, выполняются излишне.
  • Побочные эффекты распространены к ведомым устройствам репликации также.

исправление: и REPLACE и INSERT...ON DUPLICATE KEY UPDATE нестандартные, собственные изобретения, характерные для MySQL. 2003 ANSI SQL определяет MERGE оператор, который может решить ту же потребность (и больше), но MySQL не поддерживает MERGE оператор.

<час>

пользователь А пытался отредактировать это сообщение (редактирование было отклонено модераторами). Редактирование пыталось добавить заявление что INSERT...ON DUPLICATE KEY UPDATE причины новый автоинкрементный идентификатор, который будет выделен. Это верно, что новый идентификатор , генерировал , но это не используется в измененной строке.

Посмотрите демонстрацию ниже, протестированный с Сервером Percona 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 обнаруживает дубликат и вызывает обновление для изменения значения [1 118]. Отметьте эти 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 |
+----+------+
970
ответ дан 17.05.2020, 07:10
  • 1
    Для ряда: " я должен перейти к bed"... – Andy Prowl 07.03.2013, 02:46
  • 2
    О, я могу добавить, что это генерирует предупреждения (не ошибки) для недопустимого несоответствия типов, но это не генерирует предупреждение для сделанного составного первичного дубликата ключа. – Fabrício Matté 17.05.2020, 07:11
  • 3
    @LonnieBest: запрос новых функций для реализации СЛИЯНИЯ был сделан в 2005, но there' s никакой прогресс или план, насколько я знаю. bugs.mysql.com/bug.php?id=9018 – Bill Karwin 17.05.2020, 07:12
  • 4
    Интересно, есть ли у mysql группы разработчиков намерение когда-либо принятия СЛИЯНИЯ от ANSI SQL 2003? – Lonnie Best 17.05.2020, 07:12

Я обычно использую INSERT IGNORE, и это походит точно на вид поведения, которое Вы ищете также. Пока Вы знаете, что строки, которые вызвали бы индексные конфликты, не будут вставлены, и Вы планируете свою программу соответственно, она не должна доставлять неприятности.

19
ответ дан 17.05.2020, 07:06
  • 1
    Вы корректны, технически контрольная сумма используется для создания, гарантируют, что оба файла являются тем же. Вопрос, Apple должна все еще принять представления, который приводит контрольную сумму к сбою? В моем случае это вошло в обзор в течение 24 часов и одобрило приблизительно за 4 дня. Таким образом, команда обзора App Store могла бы видеть флаг, что это привело контрольную сумму к сбою, но они все еще делают обзор так или иначе. – Enrico Susatyo 04.10.2013, 14:07
  • 2
    Ключевые нарушения действительно вызывают ошибки ! См. мой комментарий в @Jens' ответ. – Floris 17.05.2020, 07:07
  • 3
    Это превращает любую ошибку в предупреждение. См. список таких случаев в моем ответе. – Bill Karwin 17.05.2020, 07:07
  • 4
    I' m коснулся этого I' ll игнорируют ошибки кроме дублирования. Это корректно или действительно ВСТАВЛЯЕТ, ИГНОРИРУЮТ, только игнорируют, только игнорируют отказ дублирования? Спасибо! – Thomas G Henry 17.05.2020, 07:08
  • 5
    That' s позор; я желаю, чтобы это только проигнорировало бы дублирующиеся отказы. – Lonnie Best 17.05.2020, 07:08

Replace В походит на опцию. Или можно свериться

IF NOT EXISTS(QUERY) Then INSERT

, Это вставит или удалит, затем вставляют. Я склонен идти для IF NOT EXISTS проверка сначала.

8
ответ дан 17.05.2020, 07:07
  • 1
    Интересно, как контрольная сумма перестала работать с нами. когда был бы это происходить! загрузчик приложения должен удостовериться это don' t происходят! Я думаю, что что-то - багги там? – hasan 27.06.2014, 22:08
  • 2
    NTuplip - то решение все еще открыто для условий состязания от вставок параллельными транзакциями. – Chris KL 17.05.2020, 07:08
  • 3
    Спасибо за быстрый ответ. I' m принимающий повсеместно, но я предполагаю, что это было бы подобно НА ДУБЛИРУЮЩЕМСЯ КЛЮЧЕВОМ ОБНОВЛЕНИИ, в котором это выполнит ненужное обновление. Это кажется расточительным, но I' m не уверенный. Любой из них должен работать. I' m задающийся вопросом, знает ли кто-либо, который является лучшим. – Thomas G Henry 17.05.2020, 07:09

НА ДУБЛИРУЮЩЕМСЯ КЛЮЧЕВОМ ОБНОВЛЕНИИ не действительно в стандарте. Это почти столь стандартно, как ЗАМЕНА. См. СЛИЯНИЕ SQL .

По существу обе команды являются версиями альтернативного синтаксиса стандартных команд.

8
ответ дан 17.05.2020, 07:08
  • 1
    Спасибо. Работавший для меня, когда я также скрестил пальцы, поскольку Вы советовали... – emreoktem 04.06.2014, 04:41

Теги

Похожие вопросы