协慌网

登录 贡献 社区

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

我正在尝试学习编写查询的最佳方法。我也了解保持一致的重要性。到现在为止,我在没有任何实际思考的情况下随机使用了单引号,双引号和反引号。

例子:

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

另外,在上面的示例中,请考虑tablecol1val1等可以是变量。

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

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

答案

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

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

MySQL 还希望DATEDATETIME文字值被单引号括起来,如'2001-01-01 00:00:00'类的字符串。咨询日期和时间文字的更多详细信息的文件,特别是替代使用连字符-在日期字符串段分隔符。

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

这些表或列标识符都不是保留字,也不使用需要引号的字符,但是无论如何我都用反引号将它们引号(稍后再说……)。

RDBMS 的本机函数(例如, 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,az,AZ$_] (基本拉丁字母,数字 0-9,美元,下划线)

您可以使用超出该范围的字符设置为表或列标识符,例如,包括空格,但是必须加引号(反引号)。

同样,尽管数字是标识符的有效字符,但标识符不能仅由数字组成。如果这样做,则必须将其包裹在反引号中。

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 的一些问题,请讨论此问题)

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