MariaDB + php: SQLSTATE [42000]: ошибка синтаксиса или нарушение доступа: 1064 on & ldquo; LIMIT 1 & rdquo; [Дубликат]

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

742
задан P̲̳x͓L̳ 21 March 2014 в 23:24
поделиться

10 ответов

Я бы рекомендовал использовать 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 |
+----+------+
904
ответ дан Peter G. 19 August 2018 в 03:06
поделиться
  • 1
    Интересно, имеет ли команда разработчиков mysql какое-либо намерение когда-либо принимать MERGE из ANSI SQL 2003? – Lonnie Best 15 July 2012 в 11:39
  • 2
    @LonnieBest: запрос функции для реализации MERGE был сделан в 2005 году, но, насколько мне известно, прогресса или плана нет. bugs.mysql.com/bug.php?id=9018 – Bill Karwin 16 July 2012 в 03:23
  • 3
    О, я могу добавить, что он генерирует предупреждения (а не ошибки) для недопустимого несоответствия типов, но не генерирует предупреждение для дублированного составного первичного ключа. – Fabrício Matté 22 August 2012 в 04:23
  • 4
    Я просто смотрел на таблицу, которая была заполнена множеством INSERT ... ON DUPLICATE KEY UPDATE ... утверждений. Много данных дублируется, и это привело к тому, что один экземпляр AI PK увеличился с 17 029 941 до 46 271 740 между двумя рядами. Это поколение нового ИИ каждый раз означает, что ваш диапазон может быть очень быстро заполнен, и вам нужно очистить его. Эта таблица всего две недели! – Ant The Knee 10 July 2014 в 19:21
  • 5
    @AntTheKnee, ахх, проблемы работы во времена Big Data. – Bill Karwin 10 July 2014 в 19:31

Я знаю, что это старо, но я добавлю это примечание на тот случай, если кто-то еще (например, я) прибудет на эту страницу, пытаясь найти информацию о INSERT..IGNORE.

Как упоминалось выше, если вы используете INSERT..IGNORE, ошибки, возникающие во время выполнения инструкции INSERT, рассматриваются как предупреждения.

. Одна вещь, которая явно не упоминается, заключается в том, что INSERT..IGNORE приведет к тому, что недопустимые значения будут скорректированы для самые близкие значения при вставке (тогда как недопустимые значения приведут к отмене запроса, если ключевое слово IGNORE не использовалось).

16
ответ дан Chris 19 August 2018 в 03:06
поделиться
  • 1
    Я не совсем уверен, что вы подразумеваете под «недопустимыми значениями». и скорректирована на что? Не могли бы вы привести пример или дальнейшее объяснение? – Marenz 26 May 2011 в 11:01
  • 2
    Это означает, что если вы вставляете неправильный тип данных в поле при использовании «INSERT IGNORE», данные будут изменены в соответствии с типом данных поля и будет вставлено потенциально недопустимое значение, тогда запрос будет продолжать работать. С "INSERT" только ошибка будет связана с неправильным типом данных, и запрос будет прерван. Это может быть нормально, когда число вставляется в varchar или текстовое поле, но вставка текстовой строки в поле с числовым типом данных приведет к плохим данным. – codewaggle 18 December 2012 в 13:02
  • 3
    @Marenz еще один пример: если ваша таблица имеет ненулевой столбец, а ваш & quot; INSERT IGNORE & quot; запрос не указывает значение для этого столбца, строка будет вставлена ​​с нулевым значением в этом столбце, независимо от того, включен ли строгий sql_mode. – Shannon 15 October 2015 в 16:47

ON DUPLICATE KEY UPDATE в стандарте не действительно . Это стандартно, как REPLACE. См. SQL MERGE .

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

7
ответ дан Chris KL 19 August 2018 в 03:06
поделиться
  • 1
    replace выполняет удаление и вставку, тогда как при повторном обновлении ключа обновляется существующая строка. некоторые отличия: auto incrementing id, позиция в строке, куча триггеров – ahnbizcad 6 April 2017 в 23:44

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

14
ответ дан David Z 19 August 2018 в 03:06
поделиться
  • 1
    Я обеспокоен тем, что буду игнорировать ошибки, кроме дублирования. Правильно ли это или INSERT IGNORE игнорирует только игнорирование отказа дублирования? Благодаря! – Thomas G Henry 14 February 2009 в 07:02
  • 2
    Это превращает любую ошибку в предупреждение. См. Список таких случаев в моем ответе. – Bill Karwin 14 February 2009 в 21:10
  • 3
    Это позор; Хотелось бы, чтобы это проигнорировало дублирование неудач. – Lonnie Best 15 July 2012 в 11:33
  • 4
    Основные нарушения вызывают ошибки ! См. Мой комментарий в ответе @Jens. – Floris 24 May 2014 в 16:57
  • 5
    @Pacerier, это зависит от того, проверяет ли ваше приложение предупреждения. Или, если он может проверить предупреждения. Например, большинство пакетов ORM не дают вам возможности. Некоторые соединители (например, JDBC) также отделяют вас от API MySQL, поэтому вы не получаете возможность проверять предупреждения. – Bill Karwin 9 March 2015 в 16:00

Если вы хотите вставить в таблицу и в конфликт первичного ключа или уникальный индекс, он будет обновлять конфликтующую строку вместо вставки этой строки.

Синтаксис:

insert into table1 set column1 = a, column2 = b on duplicate update column2 = c;

Теперь здесь этот оператор вставки может выглядеть по-другому, что вы видели ранее. Этот оператор insert пытается вставить строку в таблицу1 со значениями a и b в столбец столбца1 и столбец 2. соответственно.

Понятно, что этот подробный отчет:

Например: здесь column1 определяется как первичный ключ в таблице 1.

Теперь, если в таблице 1 нет строки, имеющей значение «a» в столбце 1. Поэтому этот оператор будет вставлять строку в таблицу.

Теперь, если в таблице 1 есть строка со значением «a» в столбце2. Таким образом, этот оператор обновит значение столбца строки с «c», где значение столбца «a».

Итак, если вы хотите вставить новую строку, иначе обновите эту строку в конфликте первичного ключа или уникальный индекс. Подробнее об этой ссылке

1
ответ дан JonathanDavidArndt 19 August 2018 в 03:06
поделиться

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

2
ответ дан LOL 19 August 2018 в 03:06
поделиться

Если вы хотите увидеть, что все это значит, вот удар по всему:

CREATE TABLE `users_partners` (
  `uid` int(11) NOT NULL DEFAULT '0',
  `pid` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`uid`,`pid`),
  KEY `partner_user` (`pid`,`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

Основной ключ основан на обоих столбцах этой таблицы быстрого сравнения. Первичный ключ требует уникальных значений.

Начнем:

INSERT INTO users_partners (uid,pid) VALUES (1,1);
...1 row(s) affected

INSERT INTO users_partners (uid,pid) VALUES (1,1);
...Error Code : 1062
...Duplicate entry '1-1' for key 'PRIMARY'

INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1);
...0 row(s) affected

INSERT INTO users_partners (uid,pid) VALUES (1,1) ON DUPLICATE KEY UPDATE uid=uid
...0 row(s) affected

обратите внимание, что выше сохранена слишком большая дополнительная работа, установив столбец равным самому себе, никакого обновления на самом деле не требуется

REPLACE INTO users_partners (uid,pid) VALUES (1,1)
...2 row(s) affected

, а теперь несколько тестов с несколькими строками:

INSERT INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
...Error Code : 1062
...Duplicate entry '1-1' for key 'PRIMARY'

INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
...3 row(s) affected

в консоли не было создано никаких других сообщений, и теперь в этих таблицах теперь есть эти 4 значения. Я удалил все, кроме (1,1), чтобы я мог протестировать с одного и того же игрового поля

INSERT INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4) ON DUPLICATE KEY UPDATE uid=uid
...3 row(s) affected

REPLACE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
...5 row(s) affected

Итак, у вас оно есть. Так как все это было сделано на свежем столе с почти отсутствием данных, а не на производстве, времена для выполнения были микроскопическими и неактуальными. Любой, кто имеет данные в реальном мире, будет более чем рад внести свой вклад.

157
ответ дан Paulus Maximus 19 August 2018 в 03:06
поделиться
  • 1
    Я запустил оба дубликата и заменил его. Мои таблицы закончились с ~ 120 тыс. Строк, причем около 30% моих строк были дублирующими. На дублированном ключе заработало 102 секунды, а замена выполнялась через 105 секунд. Для моего случая я придерживаюсь двойного ключа. – crunkchitis 18 April 2013 в 19:59
  • 2
    Протестировал выше с помощью MariaDB 10 и получил предупреждение при запуске INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4). – Floris 24 May 2014 в 16:36
  • 3
    Какую версию MySQL вы использовали для всего этого? – Radu Murzea 11 April 2016 в 13:34

Что-то важное для добавления: при использовании INSERT IGNORE и у вас есть ключевые нарушения, MySQL НЕ поднимет предупреждение!

Если вы попытаетесь, например, вставить 100 записей за раз, с одной неисправной , вы попадете в интерактивный режим:

Query OK, 99 rows affected (0.04 sec)

Records: 100 Duplicates: 1 Warnings: 0

Как видите: Нет предупреждений! Это поведение даже ошибочно описано в официальной документации Mysql.

Если ваш скрипт должен быть проинформирован, если некоторые записи не были добавлены (из-за нарушений ключа), вы должны вызвать mysql_info () и проанализировать его для значения «Duplicates».

37
ответ дан Pedro Lobito 19 August 2018 в 03:06
поделиться
  • 1
    Если вы используете PHP, вам нужно будет использовать mysqli_affected_rows() , чтобы узнать, действительно ли INSERT произошло. – Amal Murali 23 December 2013 в 07:44
  • 2
    Как MySQL 5.5, так и MariaDB 10 I do получают ошибку Cannot add or update a child row: a foreign key constraint fails , а строки (даже действительные) не добавляются. – Floris 24 May 2014 в 16:52
  • 3
    @Floris Эта ошибка возникает из-за ограничения внешнего ключа и не из-за дублирующего ключа . Я использую MySQL 5.5.28. При использовании INSERT IGNORE дублирующие ключи игнорируются без ошибок или предупреждений. – toxalot 31 October 2014 в 13:42

Если при использовании insert ignore, имеющего оператор SHOW WARNINGS; в конце вашего набора запросов, будет отображаться таблица со всеми предупреждениями, в том числе идентификаторы которых являются дубликатами.

0
ответ дан Ray Foss 19 August 2018 в 03:06
поделиться

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

IF NOT EXISTS(QUERY) Then INSERT

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

5
ответ дан Shafizadeh 19 August 2018 в 03:06
поделиться
  • 1
    Спасибо за быстрый ответ. Я предполагаю, что это будет похоже на ON DUPLICATE KEY UPDATE, поскольку оно будет выполнять ненужное обновление. Это кажется расточительным, но я не уверен. Любое из них должно работать. Мне интересно, знает ли кто, что лучше. – Thomas G Henry 14 February 2009 в 06:55
  • 2
    NTuplip - это решение по-прежнему открыто для условий гонки из вложений при одновременных транзакциях. – Chris KL 16 February 2009 в 00:28
  • 3
    REPLACE удаляет все строки в таблице с помощью сочетания any PRIMARY или UNIQUE, , затем INSERTs. Это потенциально намного больше работы, чем IODKU. – Rick James 30 January 2017 в 03:32
Другие вопросы по тегам:

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