何时在MySQL中使用单引号,双引号和后退标记

Nat*_*ate 605 mysql sql quotes

我正在尝试学习编写查询的最佳方法.我也理解保持一致的重要性.到现在为止,我已经随机使用了单引号,双引号和后退,没有任何实际想法.

例:

$query = 'INSERT INTO table (id, col1, col2) VALUES (NULL, val1, val2)';
Run Code Online (Sandbox Code Playgroud)

此外,在上面的例子中,考虑table可能是变量.

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

我一直在这里阅读类似问题的答案大约20分钟,但看起来这个问题没有明确的答案.

Mic*_*ski 585

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

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

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

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

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

NOW()不应引用RDBMS本机函数(例如,在MySQL中),尽管它们的参数受到已经提到的相同字符串或标识符引用规则的约束.

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 (?, ?, ?, ?)";
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • "*但单引号被其他RDBMS*更广泛地接受" - 使用单引号作为字符串文字由SQL标准定义(和必需) (42认同)
  • 这不是真的:_"MySQL还期望DATE和DATETIME文字值单引号为'2001-01-01 00:00:00'之类的字符串"_ (3认同)
  • @evilReiko MySQL文档似乎没有明确地引用别名引用.它将接受单个,双重或反引号的别名,但可能会受到不同ANSI SQL模式的影响.我不确定SQL规范对别名引号的要求 - 个人偏好:为了保持一致性,我引用它们与列标识符相同 - 也就是说,如果需要,我要么反复引用它们,要么如果没有则不引用它们.我不对别名使用单引号或双引号. (3认同)
  • @GuneyOzsan是的,非常脆弱.除非已根据可接受的表名列表进行验证,否则永远不要将变量用于表名 - 创建一个允许的名称数组并检查变量是否与列表中的内容匹配以使其安全使用.否则,您无法安全地转义表名变量以供使用. (2认同)
  • 迈克尔现在一切都安排好了,谢谢。我可以建议编辑图表以添加绑定变量吗?这绝对是华丽的,如果另一个可怜的灵魂过来检查`:whatever`那就更可爱了。史蒂夫·ATB (2认同)

Sal*_*n A 114

MySQL中有两种类型的引号:

  1. ' 用于包含字符串文字
  2. ` 用于包含表和列名称等标识符

然后有"一个特例.根据MySQL服务器的不同,它可以一次用于上述目的之一sql_mode:

  1. 默认情况下,"字符可用于包含字符串文字'
  2. ANSI_QUOTES模式中,该"字符可用于包围标识符`

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

SELECT "column" FROM table WHERE foo = "bar"
Run Code Online (Sandbox Code Playgroud)

ANSI_QUOTES已禁用

查询将选择"column"foo等于string 的字符串文字"bar"

ANSI_QUOTES已启用

查询将选择columnfoo等于列的列bar

什么时候用

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


Chr*_*hey 32

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

也许重要的是要提到PHP处理单引号和双引号字符串不同...

单引号字符串是'文字',几乎是WYSIWYG字符串.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
Run Code Online (Sandbox Code Playgroud)


Sta*_*arx 21

反引号通常用于表示安全,identifier并且不会意外地使用保留关键字.

例如:

Use `database`;
Run Code Online (Sandbox Code Playgroud)

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

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

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


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

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

INSERT INTO `tablename` (`id, `title`) VALUES ( NULL, title1);
Run Code Online (Sandbox Code Playgroud)

在这里,我故意忘记title1用引号括起来.现在,服务器将采用title1列名称(即标识符).因此,要表明它是一个值,您必须使用双引号或单引号.

INSERT INTO `tablename` (`id, `title`) VALUES ( NULL, 'title1');
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

会做的

INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, 'my value 1', 'my value 2')
Run Code Online (Sandbox Code Playgroud)


Kum*_*esh 14

在MySQL中,这些符号是用来分隔查询`,",'().

  1. "'用于封闭类似字符串的值"26-01-2014 00:00:00"'26-01-2014 00:00:00'.这些符号仅用于字符串,而不是聚合函数一样now,summax.

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


xda*_*azz 13

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

字符串是一个字节或字符序列,包含在单引号("'")或双引号(""")字符中.

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

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

$query = "INSERT INTO table (id, col1, col2) VALUES (NULL, 'val1', 'val2')";
Run Code Online (Sandbox Code Playgroud)

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

$query = "INSERT INTO table (id, col1, col2) VALUES (NULL, '$val1', '$val2')";
Run Code Online (Sandbox Code Playgroud)

但是,如果$val1$val2包含单引号,那将使您的SQL出错.所以你需要在sql中使用之前将其转义; 这mysql_real_escape_string就是为了什么.(虽然准备好的陈述更好.)


vip*_*iya 11

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

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

现在,假设您正在使用直接post变量进入MySQL查询,那么使用它:

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

这是将PHP变量用于MySQL的最佳实践.

  • 请永远不要在查询中直接使用未转义的用户输入! (2认同)

小智 11

这里有很多有用的答案,通常最终分为两点.

  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)
Run Code Online (Sandbox Code Playgroud)

不使用反引号时出错.

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
Run Code Online (Sandbox Code Playgroud)

但是,它123451a6是一个非常精细的标识符名称(没有后退标记).

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

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


diE*_*cho 10

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

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

$query = "INSERT INTO $table_name (id, $col1, $col2)
                 VALUES (NULL, '$val1', '$val2')";
Run Code Online (Sandbox Code Playgroud)

要么

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

单引号'':

$query = 'INSERT INTO '.$table_name.' (id, '.$col1.', '.$col2.')
             VALUES (NULL, '.$val1.', '.$val2.')';
Run Code Online (Sandbox Code Playgroud)

``当列/值名称类似于MySQL保留关键字时,请使用反向标记.

注意:如果您使用表名表示列名,那么请使用这样的返回标记:

`table_name`.`column_name` < - 注意:. 从后面的刻度中排除.


joh*_*eel 8

单引号应该用于字符串值,如VALUES()列表中所示.

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

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


Fun*_*ner 5

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

简而言之; MySQL 认为您想对其自己的表/列进行数学运算,并将“电子邮件”等连字符解释为e 减号 mail


免责声明:所以我想我会将此添加为“仅供参考”类型的答案,适用于那些完全不熟悉数据库工作并且可能不理解已经描述的技术术语的人。