我正在学习编写查询的最佳方法。我也明白始终如一的重要性。到目前为止,我没有经过任何真正的思考就随意地使用单引号、双引号和反引号。

例子:

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

同样,在上面的例子中,考虑table、col1、val1等可能是变量。

这个标准是什么?你会怎么做?

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


当前回答

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

其他回答

反勾号用于表和列标识符,但仅当标识符是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,美元,下划线)

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

另外,虽然数字是标识符的有效字符,但标识符不能只由数字组成。如果是的话,他们肯定是被反扁虱缠住了。

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

有时候不用引号是有用的……因为这会突出生成查询的代码中的问题…例如:

x和y的位置应该总是整数…

从x= y=0的表中选择*

是SQL语法错误…有点懒,但很有用……

除了所有这些(解释得很好的)答案之外,我还没有提到以下问题,我经常访问这个问答。

简单地说;MySQL认为您想在它自己的表/列上做数学运算,并将连字符(如“e-mail”)解释为e-mail。


免责声明:因此,对于那些完全不熟悉数据库的人以及可能不理解已经描述的技术术语的人,我认为我将添加这一点作为“供参考”类型的回答。

反勾号通常用来表示标识符,也可以避免意外使用保留关键字。

例如:

Use `database`;

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

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

检查这个答案,以了解更多关于反撇号。


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

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

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

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

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