何时在 MySQL 中使用单引号、双引号和反引号

When to use single quotes, double quotes, and backticks in MySQL

提问人:Nate 提问时间:7/4/2012 最后编辑:Mark AmeryNate 更新时间:10/19/2021 访问量:303935

问:

我正在尝试学习编写查询的最佳方法。我也明白保持一致的重要性。到目前为止,我一直随意使用单引号、双引号和反引号,没有任何真正的想法。

例:

$query = 'INSERT INTO table (id, col1, col2) VALUES (NULL, val1, val2)';

此外,在上面的例子中,考虑 、 、 等可能是变量。tablecol1val1

这方面的标准是什么?你是做什么工作的?

我已经在这里阅读了大约 20 分钟的类似问题的答案,但这个问题似乎没有明确的答案。

MySQL SQL 行情

评论

27赞 jarlh 11/25/2016
请注意,这是一个非常特定于MySQL的问题。一般的 SQL(即 .ISO/ANSI SQL)具有不同的引号集:双引号用于分隔标识符,例如 ,单引号用于文字,例如 .反引号从不在标准 SQL 中使用。(如果需要在标识符中包含双引号,请将其键入两次。同样,文本中的双单引号,如 .)"tablename"'this is a some text'"odd""tablename"'Conan O''Brien'

答:

745赞 Michael Berkowski 7/4/2012 #1

反引号用于表和列标识符,但仅当标识符是 MySQL 保留关键字时才需要,或者当标识符包含空格字符或超出有限集的字符时才需要(见下文) 通常建议尽可能避免使用保留关键字作为列或表标识符,以避免引用问题。

单引号应用于列表中的字符串值。MySQL也支持字符串值使用双引号,但单引号被其他RDBMS更广泛地接受,因此使用单引号而不是双引号是一个好习惯。VALUES()

MySQL还期望和文字值以字符串形式单引号,例如。有关更多详细信息,请参阅日期和时间文本文档,特别是使用连字符作为日期字符串中的段分隔符的替代方法。DATEDATETIME'2001-01-01 00:00:00'-

因此,使用您的示例,我将对PHP字符串进行双引号,并在值上使用单引号。 是一个 MySQL 关键字,并且是一个特殊(非)值,因此不加引号。'val1', 'val2'NULL

这些表或列标识符都不是保留字或使用需要引用的字符,但我还是用反引号引用了它们(稍后会详细介绍......

RDBMS原生函数(例如,在MySQL中)不应被引用,尽管它们的参数受制于已经提到的相同字符串或标识符引用规则。NOW()

Backtick (`)
table & column ───────┬─────┬──┬──┬──┬────┬──┬────┬──┬────┬──┬───────┐
                      ↓     ↓  ↓  ↓  ↓    ↓  ↓    ↓  ↓    ↓  ↓       ↓
$query = "INSERT INTO `table` (`id`, `col1`, `col2`, `date`, `updated`) 
                       VALUES (NULL, 'val1', 'val2', '2001-01-01', NOW())";
                               ↑↑↑↑  ↑    ↑  ↑    ↑  ↑          ↑  ↑↑↑↑↑ 
Unquoted keyword          ─────┴┴┴┘  │    │  │    │  │          │  │││││
Single-quoted (') strings ───────────┴────┴──┴────┘  │          │  │││││
Single-quoted (') DATE    ───────────────────────────┴──────────┘  │││││
Unquoted function         ─────────────────────────────────────────┴┴┴┴┘    

变量插值

变量的引用模式不会改变,但如果你打算直接在字符串中插入变量,在 PHP 中必须用双引号括起来。只需确保您已正确转义变量以在 SQL 中使用即可。(建议改用支持预处理语句的 API,以防止 SQL 注入)。

// Same thing with some variable replacements
// Here, a variable table name $table is backtick-quoted, and variables
// in the VALUES list are single-quoted 
$query = "INSERT INTO `$table` (`id`, `col1`, `col2`, `date`) VALUES (NULL, '$val1', '$val2', '$date')";

准备好的发言

使用准备好的语句时,请查阅文档以确定是否必须引用语句的占位符。PHP、PDO 和 MySQLi 中最流行的 API 需要不加引号的占位符,其他语言中的大多数准备好的语句 API 也是如此:

// PDO example with named parameters, unquoted
$query = "INSERT INTO `table` (`id`, `col1`, `col2`, `date`) VALUES (:id, :col1, :col2, :date)";

// MySQLi example with ? parameters, unquoted
$query = "INSERT INTO `table` (`id`, `col1`, `col2`, `date`) VALUES (?, ?, ?, ?)";

标识符中需要反引号引号的字符:

根据MySQL文档,您不需要使用以下字符集引用(反引号)标识符:

ASCII:(基本拉丁字母,数字 0-9,美元,下划线)[0-9,a-z,A-Z$_]

您可以使用超出该集的字符作为表或列标识符,例如包括空格,但必须用引号(反引号)来引用它们。

此外,尽管数字是标识符的有效字符,但标识符不能仅由数字组成。如果这样做,则必须用反引号括起来。

评论

57赞 7/14/2014
"但单引号被其他 RDBMS 更广泛地接受“——对字符串文字使用单引号是由 SQL 标准定义(并且是必需的)
5赞 Kick_the_BUCKET 4/12/2016
事实并非如此:“MySQL还要求DATE和DATETIME文本值作为字符串单引号,如'2001-01-01 00:00:00'”
5赞 Michael Berkowski 8/16/2017
@evilReiko MySQL文档似乎没有清楚地解决别名引用问题。它将接受别名的单引号、双引号或反引号,但可能会受到不同 ANSI SQL 模式的影响。我不确定 SQL 规范对别名引号的要求是什么——个人偏好:为了保持一致性,我引用它们与列标识符相同 - 也就是说,如果需要,我要么反引它们,要么不加引号。我不在别名上使用单引号或双引号。
4赞 Michael Berkowski 10/27/2018
@GuneyOzsan 是的,非常脆弱。永远不要将变量用于表名,除非它已经根据可接受的表名列表进行了验证 - 创建一个允许名称的数组,并检查变量是否与列表中的内容匹配,以使其安全使用。否则,无法安全地转义表名变量以供使用。
2赞 BeNice 12/6/2019
迈克尔现在都整理好了,谢谢。我是否可以建议编辑图表以添加绑定变量。这绝对是华丽的,如果另一个可怜的灵魂出现,那就更可爱了。ATB史蒂夫:whatever
31赞 Starx 7/4/2012 #2

反引号通常用于表示,也可以防止意外使用保留关键字identifier

例如:

Use `database`;

在这里,反引号将帮助服务器了解 实际上是数据库的名称,而不是数据库标识符。database

也可以对表名和字段名执行相同的操作。如果用反引号将数据库标识符括起来,这是一个非常好的习惯

查看答案以了解有关反引号的更多信息。


现在关于双引号和单引号(迈克尔已经提到过)。

但是,要定义一个值,您必须使用单引号或双引号。让我们看另一个例子。

INSERT INTO `tablename` (`id, `title`) VALUES ( NULL, title1);

在这里,我故意忘记用引号括起来。现在服务器将 作为列名(即标识符)。因此,要指示它是一个值,您必须使用双引号或单引号。title1title1

INSERT INTO `tablename` (`id, `title`) VALUES ( NULL, 'title1');

现在,结合 PHP,双引号和单引号使您的查询编写时间变得更加容易。让我们在您的问题中查看查询的修改版本。

$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";

现在,在 PHP 中使用双引号,您将创建变量 ,并使用它们的值,从而创建一个完全有效的查询。喜欢$val1$val2

$val1 = "my value 1";
$val2 = "my value 2";
$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";

将使

INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, 'my value 1', 'my value 2')
13赞 xkeshav 7/4/2012 #3

如果表 cols 和 values 是变量,则有两种方法:

使用双引号表示完整查询:""

$query = "INSERT INTO $table_name (id, $col1, $col2)
                 VALUES (NULL, '$val1', '$val2')";

 $query = "INSERT INTO ".$table_name." (id, ".$col1.", ".$col2.")
               VALUES (NULL, '".$val1."', '".$val2."')";

带单引号:''

$query = 'INSERT INTO '.$table_name.' (id, '.$col1.', '.$col2.')
             VALUES (NULL, '.$val1.', '.$val2.')';

当列/值名称类似于 MySQL 保留关键字时,使用反引号。``

注意:如果要使用表名表示列名,则使用反引号,如下所示:

`table_name`. <-- 注意:从反勾中排除。`column_name`.

37赞 Chris Trahey 7/4/2012 #4

(关于你的问题的SQL性质,上面有很好的答案,但如果你是PHP的新手,这也可能是相关的。

也许值得一提的是,PHP 处理单引号和双引号字符串的方式不同......

单引号字符串是“文字”,几乎是所见即所得的字符串。PHP 对双引号字符串进行解释,以便进行可能的变量替换(PHP 中的反引号并不完全是字符串;它们在 shell 中执行命令并返回结果)。

例子:

$foo = "bar";
echo 'there is a $foo'; // There is a $foo
echo "there is a $foo"; // There is a bar
echo `ls -l`; // ... a directory list
16赞 xdazz 7/4/2012 #5

MySQL和PHP中的字符串文字是相同的。

字符串是字节或字符的序列,包含在 单引号 (“'”) 或双引号 (“”“) 字符。

因此,如果您的字符串包含单引号,则可以使用双引号来引号字符串,或者如果它包含双引号,则可以使用单引号引号来引号字符串。但是,如果字符串同时包含单引号和双引号,则需要转义用于引号字符串的引号。

大多数情况下,我们对 SQL 字符串值使用单引号,因此我们需要对 PHP 字符串使用双引号。

$query = "INSERT INTO table (id, col1, col2) VALUES (NULL, 'val1', 'val2')";

你可以在PHP的双引号字符串中使用一个变量:

$query = "INSERT INTO table (id, col1, col2) VALUES (NULL, '$val1', '$val2')";

但是,如果 or 包含单引号,那将使您的 SQL 出错。因此,您需要在 sql 中使用它之前对其进行转义;这就是目的。(虽然准备好的声明更好。$val1$val2mysql_real_escape_string

161赞 Salman A 1/2/2013 #6

MySQL中有两种类型的报价:

  1. '用于括起字符串文字
  2. `用于将标识符(如表名和列名)括起来

还有一个特例。根据MySQL服务器的sql_mode,它可以一次用于上述目的之一"

  1. 默认情况下,该字符可用于将字符串文字括起来,就像"'
  2. ANSI_QUOTES模式下,该字符可用于将标识符括起来,就像"`

以下查询将根据 SQL 模式生成不同的结果(或错误):

SELECT "column" FROM table WHERE foo = "bar"

ANSI_QUOTES禁用

查询将选择字符串文本,其中 column 等于字符串"column"foo"bar"

启用ANSI_QUOTES

查询将选择列等于列的列columnfoobar

何时使用什么

  • 我建议你避免使用,这样你的代码就会独立于 SQL 模式"
  • 始终引用标识符,因为这是一种很好的做法(SO 上的很多问题都讨论了这个问题)

评论

1赞 Caius Jard 3/18/2021
或者,在ANSI_QUOTES模式下运行 MySQL,使 SQL 技能集更具可移植性,并用于字符串、标识符,并且不使用反引号。遵守标准总是好的'"
0赞 Rick 1/14/2022
对于其他有关如何在会话级别启用的信息:。然后,您可以检查该值。如果要恢复到默认值,则默认值为 :ANSI_QUOTESSET SESSION sql_mode = 'ANSI_QUOTES'; or SET SESSION sql_mode = 'ANSI';SELECT @@SESSION.sql_mode;MySQL 5.7SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
15赞 vipul sorathiya 6/16/2015 #7

结合 PHP 和 MySQL,双引号和单引号使您的查询编写时间变得更加轻松。

$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";

现在,假设您在 MySQL 查询中使用直接 post 变量,然后按以下方式使用它:

$query = "INSERT INTO `table` (`id`, `name`, `email`) VALUES (' ".$_POST['id']." ', ' ".$_POST['name']." ', ' ".$_POST['email']." ')";

这是在MySQL中使用PHP变量的最佳实践。

评论

1赞 rhavendc 5/31/2016
因此,双引号很灵活,但不能用作标识符。
1赞 jankal 12/27/2016
请不要在查询中直接使用未转义的用户输入!
1赞 vipul sorathiya 12/28/2016
@jankal这只是例子。我指定,如果您使用直接用户输入,那么 n 那么...........
1赞 RFLdev 8/16/2017
@vipulsorathiya 请在回答中说明应转义 POST 变量。您现在指向在查询中直接使用它们。对于尝试这个的初学者来说很糟糕......
11赞 john igneel 7/9/2015 #8

单引号应用于字符串值,如 VALUES() 列表中。

反引号通常用于指示标识符,并且不会意外使用保留关键字。

结合 PHP 和 MySQL,双引号和单引号使您的查询编写时间变得更加容易。

25赞 Kumar Rakesh 1/3/2017 #9

在 MySQL 中,这些符号用于分隔查询 、 和 。`"'()

  1. "或 用于将类似字符串的值括起来,或者 .这些符号仅适用于字符串,不适用于聚合函数,如 、 或 。'"26-01-2014 00:00:00"'26-01-2014 00:00:00'nowsummax

  2. `用于将表名或列名括起来,例如select `column_name` from `table_name` where id='2'

  3. (并简单地将查询的各个部分括起来,例如 .)select `column_name` from `table_name` where (id='2' and gender='male') or name='rakesh'

18赞 user5574289 1/28/2017 #10

这里有很多有用的答案,通常归结为两点。

  1. BACKQUOTES(') 用于标识符名称周围。
  2. 单引号(')用于值。

正如@MichaelBerkowski所说

反引号用于表和列标识符,但 仅当标识符是保留关键字时才需要,或者 当标识符包含空格字符或字符时 超出有限的集合(见下文) 通常建议避免 尽可能使用保留关键字作为列或表标识符, 避免报价问题。MySQL

但是,在某些情况下,标识符既不能是保留关键字,也不能包含超出有限集空格或字符,但必须需要在它们周围加上反引号。

123E10是有效的标识符名称,也是有效的文本。INTEGER

[不赘述如何获得这样的标识符名称],假设我想创建一个名为 的临时表。123456e6

反引号上没有错误。

DB [XXX]> create temporary table `123456e6` (`id` char (8));
Query OK, 0 rows affected (0.03 sec)

不使用反引号时出错。

DB [XXX]> create temporary table 123451e6 (`id` char (8));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '123451e6 (`id` char (8))' at line 1

但是,是一个完美的标识符名称(没有反引号)。123451a6

DB [XXX]> create temporary table 123451a6 (`id` char (8));
Query OK, 0 rows affected (0.03 sec)

这完全是因为也是一个指数数。1234156e6

6赞 Funk Forty Niner 2/19/2018 #11

除了所有(解释清楚的)答案外,没有提到以下内容,我经常访问这个问答。

简而言之;MySQL认为您想在自己的表/列上进行数学运算,并将连字符(例如“e-mail”)解释为减号email


免責聲明:因此,我想我会将其添加为“仅供参考”类型的答案,供那些完全不熟悉数据库并且可能不理解已经描述的技术术语的人使用。

3赞 NAVIN 8/22/2018 #12

SQL 服务器和 MySQL、PostgreySQL、Oracle 不理解双引号(“)。因此,您的查询应该没有双引号(“),并且应该只使用单引号(')。

Back-trip(') 在 SQL 中是可选的,用于表名、数据库名和列名。

如果您尝试在后端编写查询来调用 MySQL,则可以使用双引号(“)或单引号(')将查询分配给变量,例如:

let query = "select id, name from accounts";
//Or
let query = 'select id, name from accounts';

如果查询中的语句和/或尝试使用值和/或值(即字符串),请对这些值使用单引号('),例如:whereinsertupdate

let querySelect = "select id, name from accounts where name = 'John'";
let queryUpdate = "update accounts set name = 'John' where id = 8";
let queryInsert = "insert into accounts(name) values('John')";

//Please not that double quotes are only to be used in assigning string to our variable not in the query
//All these below will generate error

let querySelect = 'select id, name from accounts where name = "John"';
let queryUpdate = 'update accounts set name = "John" where id = 8';
let queryInsert = 'insert into accounts(name) values("John")';

//As MySQL or any SQL doesn't understand double quotes("), these all will generate error.

如果你想避免这种混淆,什么时候使用双引号(“)和单引号('),建议坚持使用单引号('),这将包括反斜杠(),如:

let query = 'select is, name from accounts where name = \'John\'';

当我们必须分配一些动态值并执行一些字符串连接时,就会出现 double(“) 或 single(') 引号的问题,例如:

let query = "select id, name from accounts where name = " + fName + " " + lName;
//This will generate error as it must be like name = 'John Smith' for SQL
//However our statement made it like name = John Smith

//In order to resolve such errors use
let query = "select id, name from accounts where name = '" + fName + " " + lName + "'";

//Or using backslash(\)
let query = 'select id, name from accounts where name = \'' + fName + ' ' + lName + '\'';

如果需要进一步的许可,请遵循 JavaScript 中的引号

2赞 jxwd 12/2/2020 #13

有时不使用引号很有用......因为这会突出显示生成查询的代码中的问题...例如:

其中 x 和 y 应始终为整数......

从中选择 *,其中 x= 和 y=0table

是 SQL 语法错误...有点懒惰,但可能很有用......