我正在尝试学习编写查询的最佳方法。我也理解保持一致的重要性。到目前为止,我已经随机使用单引号,双引号和反引号而没有任何实际想法。
示例:
$query = 'INSERT INTO table (id, col1, col2) VALUES (NULL, val1, val2)';
此外,在上面的示例中,请考虑table
,col1
,val1
等可能是变量。
这是什么标准?你做什么的?
我一直在这里阅读类似问题的答案大约20分钟,但似乎没有明确答案这个问题。
答案 0 :(得分:554)
反引号用于表和列标识符,但仅在标识符为MySQL reserved keyword时,或者当标识符包含空格字符或超出有限集的字符时才需要(见下文)。通常建议使用尽可能避免使用保留关键字作为列或表标识符,避免引用问题。
单引号应该用于VALUES()
列表中的字符串值。 MySQL也支持双引号用于字符串值,但是单引号被其他RDBMS更广泛地接受,因此使用单引号而不是双引号是一个好习惯。
MySQL还希望DATE
和DATETIME
字面值单引号为'2001-01-01 00:00:00'
之类的字符串。有关详细信息,请参阅the Date and Time Literals文档,特别是在日期字符串中使用连字符-
作为段分隔符的替代方法。
因此,使用您的示例,我会双引号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中使用。 (It is recommended to use an API supporting prepared statements instead, as protection against SQL injection)。
// 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 (?, ?, ?, ?)";
According to MySQL documentation,您不需要使用以下字符集引用(反引号)标识符:
ASCII:
[0-9,a-z,A-Z$_]
(基本拉丁字母,数字0-9,美元,下划线)
您可以使用超出该组的字符作为表或列标识符,例如包括空格,但是必须引用(反引号)它们。
答案 1 :(得分:109)
MySQL中有两种类型的引号:
'
用于封闭字符串文字`
用于包含表格和列名称等标识符然后有"
这是一个特例。根据MySQL服务器的sql_mode
,它可以一次用于一个上述目的:
"
字符可用于包围字符串文字,就像'
ANSI_QUOTES
模式下,"
字符可用于包含标识符,就像`
SELECT "column" FROM table WHERE foo = "bar"
查询将选择字符串文字"column"
,其中列foo
等于字符串"bar"
查询将选择列column
,其中列foo
等于列bar
"
,以便您的代码独立于SQL模式答案 2 :(得分:29)
(上面有关于你的问题的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
答案 3 :(得分:19)
反引号通常用于指示identifier
以及安全意外使用Reserved Keywords。
例如:
Use `database`;
这里的反引号将帮助服务器理解database
实际上是数据库的名称,而不是数据库标识符。
可以对表名和字段名执行相同的操作。如果用反引号包装数据库标识符,这是一个非常好的习惯。
检查this回答以了解有关反引号的更多信息。
现在关于双引号&单引号(迈克尔已经提到过)。
但是,要定义一个值,您必须使用单引号或双引号。让我们看另一个例子。
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')
答案 4 :(得分:12)
在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'
(
和)
只包含查询的部分内容,例如select `column_name` from `table_name` where (id='2' and gender='male') or name='rakesh'
。
答案 5 :(得分:11)
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
的用途。 (虽然准备好的陈述更好。)
答案 6 :(得分:10)
结合PHP和MySQL,双引号和单引号使您的查询编写时间变得更加容易。
@FormParam("productName") String productName
现在,假设您在MySQL查询中使用了直接post变量,那么就这样使用它:
$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";
这是将PHP变量用于MySQL的最佳实践。
答案 7 :(得分:9)
如果表cols和values是变量,那么有两种方法:
使用双引号""
完整查询:
$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`
< - 注意:从后面的标记中排除.
。
答案 8 :(得分:9)
这里有很多有用的答案,通常最终分为两点。
和@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
也是一个指数。
答案 9 :(得分:7)
单引号应该用于字符串值,例如VALUES()列表。
反引号通常用于表示标识符,并且不会意外使用保留关键字。
结合PHP和MySQL,双引号和单引号使您的查询编写时间变得更加容易。
答案 10 :(得分:2)
除了所有(解释清楚的)答案之外,还没有提到以下内容,而且我经常访问这个Q& A.
简而言之; MySQL认为你想在自己的表/列上做数学并解释连字符,例如"电子邮件"作为e
减去 mail
。
免责声明:所以我想我会把它添加为" FYI"对于那些完全不熟悉数据库并且可能不了解已经描述的技术术语的人来说,答案的类型。
答案 11 :(得分:0)
SQL服务器和MySQL,PostgreySQL,Oracle不理解双引号(“)。因此,您的查询应不含双引号(”),而应仅使用单引号(')。
Back-trip(`)在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 + '\'';
如果需要进一步许可,请遵循quotes in JavaScript
答案 12 :(得分:0)
有时不使用引号是很有用的...,因为这可能会突出显示生成查询的代码中的问题...例如:
x和y始终应为整数...
选择*从table
中x = AND y = 0
是SQL语法错误...有点懒,但可能有用...