Ошибка синтаксиса из-за использования зарезервированного слова в качестве имени таблицы или столбца в MySQL

Я пытаюсь выполнить простой запрос MySQL, как показано ниже:

INSERT INTO user_details (username, location, key)
VALUES ('Tim', 'Florida', 42)

Но я получаю следующую ошибку:

У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с 'key) VALUES ('Tim', 'Florida', 42)' в строке 1

Как я могу исправить проблему?

Ответ 1

Проблема

В MySQL некоторые слова типа SELECT, INSERT, DELETE и т.д. являются зарезервированными словами. Поскольку они имеют особое значение, MySQL рассматривает его как синтаксическую ошибку всякий раз, когда вы используете их как имя таблицы, имя столбца или другой идентификатор - если вы не окружите идентификатор обратными окнами.

Как отмечено в официальных документах, в разделе 10.2 Имена объектов схемы (выделено мной):

Некоторые объекты в MySQL, включая базу данных, таблицу, индекс, столбец, псевдоним, представление, хранимую процедуру, раздел, табличное пространство и другие имена объектов, называются идентификаторами.

...

Если идентификатор содержит специальные символы или является зарезервированным словом, вы должны указывать его всякий раз, когда вы ссылаетесь на него.

...

Символом кавычки идентификатора является обратная сторона ( "`" ):

Полный список ключевых слов и зарезервированных слов можно найти в разделе 10.3 Ключевые слова и зарезервированные слова. На этой странице слова, за которыми следует "(R)", являются зарезервированными словами. Ниже перечислены некоторые зарезервированные слова, в том числе многие, которые, как правило, вызывают эту проблему.

  • ADD
  • И
  • перед
  • ПО
  • ВЫЗОВ
  • CASE
  • УСЛОВИЕ
  • DELETE
  • DESC
  • ОПИСАТЬ
  • С
  • GROUP
  • В
  • INDEX
  • INSERT
  • ИНТЕРВАЛ
  • IS
  • KEY
  • LIKE
  • LIMIT
  • LONG
  • MATCH
  • НЕ
  • OPTION
  • ИЛИ
  • ORDER
  • PARTITION
  • ЛИТЕРАТУРЫ
  • SELECT
  • TABLE
  • TO
  • UPDATE
  • WHERE

Решение

У вас есть два варианта.

1. Не используйте зарезервированные слова в качестве идентификаторов

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

У этого есть несколько преимуществ:

  • Это исключает возможность того, что вы или другой разработчик, использующий вашу базу данных, случайно напишете синтаксическую ошибку из-за забывания или не зная, что конкретный идентификатор является зарезервированным словом. В MySQL много зарезервированных слов, и большинство разработчиков вряд ли узнают их все. Не используя эти слова в первую очередь, вы избегаете оставлять ловушки для себя или будущих разработчиков.

  • Средство цитирования идентификаторов отличается между диалектами SQL. Хотя MySQL использует обратные ссылки для цитирования идентификаторов по умолчанию, ANSI-совместимый SQL (а также MySQL в режиме ANSI SQL, как указано здесь) использует двойные кавычки для цитирования идентификаторов. Таким образом, запросы, которые цитируют идентификаторы с backticks, менее переносимы на другие диалекты SQL.

Чисто ради уменьшения риска будущих ошибок это обычно более разумный ход действий, чем обратная ссылка на идентификатор.

2. Использовать backticks

Если переименование таблицы или столбца невозможно, заверните оскорбительный идентификатор в backticks (`), как описано в предыдущей цитате из 10.2 Объект схемы Имена.

Пример демонстрации использования (взято из 10.3 Ключевые слова и зарезервированные слова):

mysql> CREATE TABLE interval (begin INT, end INT);
ERROR 1064 (42000): You have an error in your SQL syntax.
near 'interval (begin INT, end INT)'

mysql> CREATE TABLE `interval` (begin INT, end INT);
Query OK, 0 rows affected (0.01 sec)

Аналогично, запрос из вопроса может быть исправлен путем обертывания ключевого слова key в backticks, как показано ниже:

INSERT INTO user_details (username, location, `key`)
VALUES ('Tim', 'Florida', 42)";               ^   ^