这个问题在这里已经有答案了:

我有一个数据库,其中包含约翰·多伊等姓名。不幸的是,其中一些名字包含引号,例如 Keiran O'Keefe。现在,当我尝试搜索此类名称时,如下所示:

SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe' 

我(可以理解)收到一个错误。

我该如何防止此错误发生。我正在使用 Oracle 和 PLSQL。

有帮助吗?

解决方案

转义字符是 ',因此您需要用两个引号替换引号。

例如,

SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe'

变成

SELECT * FROM PEOPLE WHERE SURNAME='O''Keefe'

也就是说,您自己这样做可能是不正确的。您的语言可能具有转义字符串以便在 SQL 中使用的功能,但更好的选择是使用参数。通常其工作原理如下。

你的 SQL 命令是:

SELECT * FROM PEOPLE WHERE SURNAME=?

然后,当您执行它时,您传入“O'Keefe”作为参数。

因为 SQL 是在设置参数值之前解析的,所以参数值无法改变 SQL 的结构(如果您想使用不同的参数多次运行相同的语句,甚至会更快一些)。

我还应该指出,虽然您的示例只会导致错误,但如果不适当地转义字符串,您就会面临许多其他问题。看 http://en.wikipedia.org/wiki/SQL_injection 一个好的起点或以下经典 xkcd漫画.

alt text

其他提示

Oracle 10的解决方案是

SELECT * FROM PEOPLE WHERE SURNAME=q'{O'Keefe}'

正如 Matt 所建议的,参数化查询是您的朋友。

Command = SELECT * FROM PEOPLE WHERE SURNAME=?

它们会保护您免受以下问题带来的头痛

  • 带引号的字符串
  • 使用日期查询
  • SQL注入

使用参数化 SQL 还有其他好处,它可以减少 Oracle 解析语句所需的工作量,从而减少 Oracle 中的 CPU 开销(以及其他资源)。如果不使用参数(我们在 Oracle 中称其为绑定变量),则“select * from foo where bar='cat'”和“select * from foo where bar='dog'”将被视为单独的语句,其中“ select * from foo where bar=:b1" 是相同的语句,这意味着语法、引用对象的有效性等......不需要再次检查。使用绑定变量时偶尔会出现问题,这些问题通常表现为无法获得最有效的 SQL 执行计划,但有解决方法,这些问题实际上取决于您使用的谓词、索引和数据倾斜。

输入过滤通常在语言层而不是数据库层完成。
php 和 .NET 都有各自的用于转义 sql 语句的库。检查您的语言,看看有什么可用的。
如果您的数据是可信的,那么您只需进行字符串替换即可在 ' 前面添加另一个 ' 来转义它。通常,如果输入不存在任何恶意风险,这就足够了。

我想一个很好的问题是你使用什么语言?
在 PHP 中你会这样做:SELECT * FROM PEOPLE WHERE SURNAME='mysql_escape_string(O'Keefe)'
但由于您没有指定语言,我建议您研究转义字符串函数 mysql 或您语言中的其他函数。

如果您使用 Zend Framework,这里的代码是处理报价的

$db = Zend_Db_Table_Abstract::getDefaultAdapter();

$db->quoteInto('your_query_here = ?','your_value_here');

例如 ;

//SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe' will become
SELECT * FROM PEOPLE WHERE SURNAME='\'O\'Keefe\''

在 Google 上发现的年龄在 30 岁以下...

Oracle SQL 常见问题解答

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top