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

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

示例:

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

同样,在上面的例子中,考虑tablecol1val1等可能是变量。

这个的标准是什么?你是做什么的?

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

279887 次浏览

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

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

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

因此,使用您的示例,我将双引号PHP字符串并对值'val1', 'val2'使用单引号。NULL是一个MySQL关键字,也是一个特殊(非)值,因此没有引号。

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

不应该引用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,a-z,A-Z$_](基本拉丁字母,数字0-9,美元,下划线)

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

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

反标通常用于表示identifier以及安全不小心使用保留关键字

例如:

Use `database`;

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

对于表名和字段名也可以这样做。如果您用反引号包装数据库标识符,这是一个非常好习惯

检查这个答案以了解有关反向标记的更多信息。


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

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

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

这里我故意忘记用引号包装title1。现在服务器将title1作为列名(即标识符)。因此,要表明它是一个值,您必须使用双引号或单引号。

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')

如果表和值是变量,那么有两种方法:

使用双引号""完成查询:

$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`<--注意:从后勾号中排除.

(关于你的问题的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

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')";

但是如果$val1$val2包含单引号,那将使您的SQL错误。因此您需要在它在sql中使用之前对其进行转义;这就是mysql_real_escape_string的用途。(尽管准备好的语句更好。)

MySQL中有两种类型的引号:

  1. '用于封闭字符串文字
  2. `用于包含标识符,例如表和列名

然后是",这是一个特例。根据MySQL服务器的sql_mode,它可以一次用于上述目的的一个

  1. 默认通过"字符可用于包围字符串文字,就像'一样
  2. ANSI_QUOTES模式下,"字符可用于包围标识符,就像`一样

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

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

ANSI_QUOTES残疾

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

ANSI_QUOTES启用

查询将选择列column,其中列foo等于列bar

什么时候用什么

  • 我建议您避免使用",以便您的代码独立于SQL模式
  • 总是引用标识符,因为这是一个很好的做法(SO上有很多问题讨论这个)

结合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变量的最佳实践。

单引号应该用于字符串值,就像在VALUES()列表中一样。

反引号通常用于指示标识符,以及防止意外使用保留关键字。

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

在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'

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

  1. BACKTICKS(')用于标识符名称。
  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也是一个指数。

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

简而言之;MySQL认为你想做数学在其自己的表/列上,并将连字符(例如“电子邮件”)解释为email


免责声明:所以我想我会把这个作为一个“FYI”类型的答案添加给那些对数据库工作完全陌生并且可能不理解已经描述的技术术语的人。

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

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

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

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

如果您的查询中有where语句和/或尝试insert值和/或update值为字符串,则对这些值使用单引号('),例如:

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\'';

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

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中的引号

有时不使用引号是有用的……因为这可以突出显示生成查询的代码中的问题……例如:

其中x和y应该总是整数…

选择*fromtable其中x=AND y=0

是一个SQL语法错误……有点懒,但可能有用……