由于在 MySQL 中使用保留字作为表名或列名导致的语法错误

Posted

技术标签:

【中文标题】由于在 MySQL 中使用保留字作为表名或列名导致的语法错误【英文标题】:Syntax error due to using a reserved word as a table or column name in MySQL 【发布时间】:2014-05-03 15:29:22 【问题描述】:

我正在尝试执行一个简单的 mysql 查询,如下所示:

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

但我收到以下错误:

ERROR 1064 (42000):您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的 'key) VALUES ('Tim', 'Florida', 42)' 附近使用正确的语法

我该如何解决这个问题?

【问题讨论】:

如果您被重定向到这里,但您没有收到任何错误消息,您可能没有进行错误检查。请寻找有关如何为您的语言、库和/或工具执行此操作的建议——不要在每次出现问题时都在这里发布。谢谢! 为什么只有MySQL?这不是跨技术/语言的问题吗?这样的参考/规范问题/答案不应该适用于标签吗?我们是否会单独为SQLServer 提供另一个类似的参考 QA,因为反引号不适用于那里;或CC#VB,我们最终可能会得到一百个这样的参考QA? @abhitalks:因为每个实现都有不同的 SQL 风格,适用于 MySQL 的可能不一定适用于其他风格。 如果各个社区认为需要它,可能会出现参考问题,否则我不会担心。拥有十几个参考问题胜过拥有数千个重复问题 IMO。 我在这里应用了 wiki 锁,因为它开始积累大量没有添加任何内容的答案。 【参考方案1】:

问题

在 MySQL 中,SELECTINSERTDELETE 等某些单词是保留字。由于它们具有特殊含义,因此当您将它们用作表名、列名或其他类型的标识符时,MySQL 会将其视为语法错误 - 除非您用反引号将标识符括起来。

如官方文档中所述,在10.2 Schema Object Names 部分(已添加重点):

MySQL 中的某些对象,包括数据库、表、索引、列、别名、视图、存储过程、分区、表空间和其他对象名称称为标识符 .

...

如果标识符包含特殊字符或者是保留字,您必须在引用它时引用它。

...

标识符引号字符是反引号(“`”):

关键字和保留字的完整列表可以在10.3 Keywords and Reserved Words 部分找到。在该页面中,后跟“(R)”的单词是保留字。下面列出了一些保留字,包括许多可能会导致此问题的保留字。

添加 和 之前 作者 致电 案例 条件 删除 DESC 描述 来自 集团 在 索引 插入 间隔 是 钥匙 喜欢 限制 长 匹配 不是 选项 或 订购 分区 排名 参考文献 选择 表格 到 更新 在哪里

解决方案

你有两个选择。

1。不要使用保留字作为标识符

最简单的解决方案就是避免使用保留字作为标识符。您可能会为您的列找到另一个不是保留字的合理名称。

这样做有几个好处:

它消除了您或使用您的数据库的其他开发人员由于忘记或不知道特定标识符是保留字而意外写入语法错误的可能性。 MySQL 中有很多保留字,大多数开发人员不太可能知道所有保留字。一开始就不使用这些词,可以避免给自己或未来的开发者留下陷阱。

引用标识符的方式因 SQL 方言而异。虽然 MySQL 默认使用反引号来引用标识符,但符合 ANSI 的 SQL(实际上是 ANSI SQL 模式下的 MySQL,如 here 所述)使用双引号来引用标识符。因此,使用反引号引用标识符的查询不太容易移植到其他 SQL 方言中。

纯粹是为了减少未来出错的风险,这通常是比反引号-引用标识符更明智的做法。

2。使用反引号

如果无法重命名表或列,请将有问题的标识符用反引号 (`) 括起来,如前面 10.2 Schema Object Names 的引用所述。

一个演示用法的例子(取自10.3 Keywords and Reserved Words):

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包裹在反引号中来修复,如下所示:

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

【讨论】:

-1。我认为建议在这个问题的参考答案中使用不带反引号的开始和结束是特别邪恶的。更好的做法是使用反引号、句点,而不必知道哪个关键字是保留的或非保留的。 @MarcAlff: beginendnot 保留字。上面的例子只是为了演示如何使用反引号来解决错误消息。并且干脆不使用保留字比盲目地反引号更好的做法——即使在不需要它们时也引用所有标识符。 我同意解决方案 1 更好,因为有人可以实际选择标识符名称。当名称无法更改时,如在解决方案 2 中,必须调查哪些标识符是关键字,以及这些关键字是否保留(即使将来的版本?),这是一个复杂的来源。顺便说一句,删除了 -1,因为示例实际上来自手册。 新的保留字在 MySQL 中经常被创建,并且有新的版本。例如,MySQL 5.7 中的非阻塞。系统地引用往往更能适应变化,并有助于升级。至于删除-1,我很乐观。你是对的,由于这个计时器,我的移除失败。 使用保留字作为标识符的另一个缺点:它使您无法搜索代码。如果您将其中一张表命名为Table,那么搜索它会返回太多误报。

以上是关于由于在 MySQL 中使用保留字作为表名或列名导致的语法错误的主要内容,如果未能解决你的问题,请参考以下文章

9.6. MySQL中保留字的处理

在ASP中SQL语句中表名或列名为啥要加中括号

oraclede中数据定义语言

PHP PDO 语句可以接受表名或列名作为参数吗?

MySQL之SELECT 语句详解

在列名中使用保留字