如何在MySql中转义单引号(撇号)?

191

MySQL文档中说应该使用\'。然而,scite和mysql都显示''可行。我尝试了一下,它也可以工作。我该怎么办?


1
你是在讨论 '' 还是 \' 正确的用法? - Raptor
如果我没记错的话,\' 是MySQL特有的,而''则符合ANSI SQL标准。 - apokryfos
根据SQL的实现方式,' ''' ,' ''和有时'[']'将允许从代码中退出。除此之外,任意数量的Unicode '替换将绕过此检查。整个游戏的关键在于滥用基于''的转义质量,它要求最终的'计数为偶数而不是奇数。如果通过将多个转义方法混合在一起使其变成奇数,则可以打败转义并注入原始SQL。故事的寓意:永远不要使用字符串插值,总是使用准备好的语句。 - Shayne
10个回答

248

你引用的MySQL文档实际上比你提到的内容多一些。它还说:

在用“'”引用的字符串中,“'”可以写成“''”。

(此外,你链接到的是MySQL 5.0版本的表格8.1 特殊字符转义序列, 当前版本是5.6 — 但当前的表格8.1 特殊字符转义序列看起来相似。)

我认为Postgres关于backslash_quote (string)参数的注释很有启发性:

这控制着在字符串文字中引号是否可以由\'表示。表示引号的首选SQL标准方式是将其加倍(''),但PostgreSQL历史上也接受\'。然而,使用\'会产生安全风险...
对我来说,使用重复的单引号字符比使用反斜杠转义单引号更好、更长远的选择。
现在,如果您还想添加语言选择、SQL数据库选择及其非标准特性以及查询框架选择到方程式中,那么您可能会得出不同的选择。您没有提供太多关于您的限制的信息。

56

标准的SQL使用双引号;MySQL必须接受这一点才能合理地遵守标准。

'He said, "Don''t!"'

1
+1. 在哪里说应该用 '' 转义而不是 http://dev.mysql.com/doc/refman/5.0/en/string-literals.html#character-escape-sequences? - user4951
它说的是“可能”而不是“应该”,但信息在那里(在表格下方):有几种方法可以在字符串中包含引号字符:
  • 用“'”引用的字符串中的“'”可以写成“''”。
  • 用“"”引用的字符串中的“"”可以写成“""”。
  • 在引号字符前加上转义字符(“\”)。
- Jonathan Leffler
1
这是通过将撇号加倍来转义的最佳方法。 - Alex _TNT

15

我认为user2087510的意思是:

name = 'something'
name = name.replace("'", "\\'")

我也成功地使用过这个。


3
那些排名靠前的答案对我没用,而这个答案却有效。 - Jared
3
为什么要用 \' 而不是 '? - biniam
@biniam_Ethiopia 第二个\是对第一个\的转义。 - Juha Untinen
2
可能存在安全问题。如果字符串已经包含',则可能会发生SQL注入攻击,因此您需要插入一个\,现在该字符将作为\'出现在字符串中并终止该字符串。请改用name.replace("'", "''")。 - Garr Godfrey

10

我知道有三种方法。第一种不是最好的,第二种是大多数编程语言中常用的方法:

  1. 使用另一个单引号:'I mustn''t sin!'
  2. 在单引号'之前使用转义字符\'I mustn\'t sin!'
  3. 使用双引号来包含字符串,而不是单引号:"I mustn't sin!"

我的个人偏好是使用 \',因为它被许多编程语言所支持,但是 '' 被更多的 SQL 方言所支持,所以使用选项1更好以确保兼容性。例如,Sqlite 不支持反斜杠转义。 - okdewit

7

'的位置上,只需写入''。也就是说,需要写入两个'


1
使用撇号两次代替一个撇号 - MRRaja

6

这里有一个例子:

SELECT * FROM pubs WHERE name LIKE "%John's%"

只需使用双引号来包含单引号。

如果您坚持使用单引号(并需要转义字符):

SELECT * FROM pubs WHERE name LIKE '%John\'s%'

1
也许略有偏题,但也许您来到这里是为了寻找一种方法来清理来自HTML表单的文本输入,以便当用户输入撇号字符时,将其写入基于SQL的数据库表格时不会出错。有几种方法可以做到这一点,您可能还想了解一下SQL注入。 以下是使用PHP中的准备语句和绑定参数的示例:
$input_str = "Here's a string with some apostrophes (')";
// sanitise it before writing to the DB (assumes PDO)
$sql = "INSERT INTO `table` (`note`) VALUES (:note)";
try {
    $stmt = $dbh->prepare($sql);
    $stmt->bindParam(':note', $input_str, PDO::PARAM_STR);
    $stmt->execute();
} catch (PDOException $e) {
    return $dbh->errorInfo();
}
return "success";

在特殊情况下,您可能希望使用其HTML实体引用存储撇号,PHP具有htmlspecialchars()函数,它将把它们转换为'。正如注释所示,这不应作为适当的净化替代品使用,如所示例子。

编码不是用于存储,而是用于显示。使用预处理语句。 - mickmackusa
我同意准备语句是安全可靠的黄金标准。我强调的是一种特定情况,即您可能希望将文本数据存储为HTML,在这种情况下,我的方法是在使用绑定参数之外的补充,而不是替代。输入HTML,输出HTML。 - Grindlay
我认为你的回答开始有了一个好的观点,但后来变得无力。在这种情况下,如果“简单选项”是致命缺陷,请不要向新手推荐它。 - Regular Jo

0

请不要只是在答案中发布一些工具或库。至少在答案中演示它如何解决问题。 - Baum mit Augen
那样行不通。你忘记转义了一些东西。replace(/'/g, "\'") - Michael

0

我认为如果你有任何带撇号的数据点,你可以在撇号前面再加一个撇号。

例如:'This is John's place'

在这里,MYSQL会将其视为两个句子 'This is John' 's place'

你可以写成 'This is John''s place'。我认为这样应该可以正常工作。


-2

永远不要这样做。始终使用“预处理语句”/“绑定参数”,您的SQL绝不能包含来自语言(PHP / Java / C# /任何语言)的原始参数。 - Regular Jo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接