我正在学习编写查询的最佳方法。我也明白始终如一的重要性。到目前为止,我没有经过任何真正的思考就随意地使用单引号、双引号和反引号。
例子:
$query = 'INSERT INTO table (id, col1, col2) VALUES (NULL, val1, val2)';
同样,在上面的例子中,考虑table、col1、val1等可能是变量。
这个标准是什么?你会怎么做?
我已经在这里看了大约20分钟类似问题的答案,但这个问题似乎没有明确的答案。
我正在学习编写查询的最佳方法。我也明白始终如一的重要性。到目前为止,我没有经过任何真正的思考就随意地使用单引号、双引号和反引号。
例子:
$query = 'INSERT INTO table (id, col1, col2) VALUES (NULL, val1, val2)';
同样,在上面的例子中,考虑table、col1、val1等可能是变量。
这个标准是什么?你会怎么做?
我已经在这里看了大约20分钟类似问题的答案,但这个问题似乎没有明确的答案。
当前回答
反勾号用于表和列标识符,但仅当标识符是MySQL保留关键字时才需要,或者当标识符包含空白字符或超出限定集的字符时(见下文)。通常建议尽可能避免使用保留关键字作为列或表标识符,以避免引用问题。
单引号应该用于像values()列表中的字符串值。MySQL对字符串值也支持双引号,但是单引号被其他RDBMS更广泛地接受,因此使用单引号而不是双引号是一个好习惯。
MySQL还要求DATE和DATETIME文本值单引号作为字符串,如'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,美元,下划线)
您可以使用该集合之外的字符作为表或列标识符,例如,包括空格,但必须引用(反引号)它们。
另外,虽然数字是标识符的有效字符,但标识符不能只由数字组成。如果是的话,他们肯定是被反扁虱缠住了。
其他回答
有时候不用引号是有用的……因为这会突出生成查询的代码中的问题…例如:
x和y的位置应该总是整数…
从x= y=0的表中选择*
是SQL语法错误…有点懒,但很有用……
反勾号用于表和列标识符,但仅当标识符是MySQL保留关键字时才需要,或者当标识符包含空白字符或超出限定集的字符时(见下文)。通常建议尽可能避免使用保留关键字作为列或表标识符,以避免引用问题。
单引号应该用于像values()列表中的字符串值。MySQL对字符串值也支持双引号,但是单引号被其他RDBMS更广泛地接受,因此使用单引号而不是双引号是一个好习惯。
MySQL还要求DATE和DATETIME文本值单引号作为字符串,如'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,美元,下划线)
您可以使用该集合之外的字符作为表或列标识符,例如,包括空格,但必须引用(反引号)它们。
另外,虽然数字是标识符的有效字符,但标识符不能只由数字组成。如果是的话,他们肯定是被反扁虱缠住了。
在MySQL中,这些符号用于分隔查询',','和()。
或'用于封闭类似字符串的值"26-01-2014 00:00:00"或"26-01-2014 00:00:00"。这些符号只用于字符串,而不是像now、sum或max这样的聚合函数。 ’用于包含表名或列名,例如:select ' column_name ' from ' table_name ' where id='2' (和)简单地包含查询的部分,例如从' table_name '中选择' column_name ' where (id='2' and gender='male')或name='rakesh'。
单引号应该用于像values()列表中的字符串值。
反勾号通常用来表示标识符,也可以避免意外使用保留的关键字。
在PHP和MySQL的组合中,双引号和单引号使您的查询编写时间更容易。
MySQL中有两种类型的引号:
'用于封装字符串字面量 ’用于包含表名和列名等标识符
然后是“这是一个特例”。根据MySQL服务器的sql_mode,它可以同时用于上述目的之一:
默认情况下,"字符可以用来包含字符串字面量,就像' 在ANSI_QUOTES模式中,“字符可以用来包含标识符,就像'
以下查询将根据SQL模式产生不同的结果(或错误):
SELECT "column" FROM table WHERE foo = "bar"
ANSI_QUOTES禁用
该查询将选择字符串字面值"column",其中column foo等于字符串"bar"
ANSI_QUOTES启用
该查询将选择column foo等于column bar的列列
什么时候用什么
我建议您避免使用“”,这样您的代码就独立于SQL模式 总是引用标识符,因为这是一个很好的实践(很多关于SO的问题都讨论了这个)