在SQL 2005/2008中转义双引号

我有一家最近加入的国际公司,名为“BLA”BLAHBLAH“Ltd。(双引号是该名称的一部分。)

每当用户尝试搜索此公司时,通过输入“Blah或其他影响,搜索失败并在SQL Server中出现语法错误。

如何逃避这一点,以便搜索不会失败?

示例SQL:

SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect FROM RussoundGeneral.dbo.Company c LEFT JOIN RussoundGeneral.dbo.CompanyMax cm ON (cm.companyId = c.companyId and cm.maxID is not null) WHERE CONTAINS ( companyName, '"BLAH*' ) GROUP BY c.companyID, c.companyName, c.dateAdded ORDER BY c.companyName ASC 

不幸的是,双引号在FTI中具有特殊含义,因此即使您对其进行参数化,FTI引擎也会将其视为短语分隔符。 我不确定在FTI搜索中是否有一种简单的方法可以包含双引号。 括号也是一个特殊字符,但可以用引号括起来作为查询术语 – 但不是AFAIK双引号。

更新

一些搜索表明将引号翻倍于“”可能会修复它 – 值得一试。 就个人而言,我会在数据库中执行此操作,因为这是一个TSQL实现细节。

同样,在传递给FTI之前’需要加倍”(完全独立于TSQL转义),

使用参数化查询,所有引用的问题都将消失。

编辑:如果您不让他们在CONTAINS中输入多个单词,请通过删除引号来清理参数。 无论多字搜索如何,通过删除引号来消毒输入可能无论如何都可以工作。

我强烈怀疑你是在动态构建SQL – 例如

 // Bad code, do not use! string sql = "SELECT * FROM Foo WHERE X LIKE '" + input + "%'"; 

出于多种原因,这是一个非常非常糟糕的想法 – 最值得注意的是SQL注入攻击 。 而是使用参数化的SQL语句,分别指定参数。

有关如何正确执行此操作的示例,请查看sql-injection标记的各种问题答案。

这是一个理论上的答案,但也许它会有所帮助。 简短版本是“在查询中使用参数”,但它有助于理解完整的细节。

在标准SQL中,字符串用单引号括起来,嵌入的单引号用一行中的两个单引号表示:

 SELECT * FROM SomeWhere WHERE SomeThing = 'He said, "Don''t do it!"'; 

在SQL的某些方言中,您可以用双引号关闭字符串; 然后你需要加倍双引号来嵌入双引号的单个实例:

 SELECT * FROM SomeWhere WHERE SomeThing = "He said, ""Don't do it!""'; 

从问题中不清楚公司名称是否包括外部双引号以及中间名称,或者它是否仅包含中间名称。 但是,原则上规则是相同的。 假设所有三个双引号都是必需的,并且在SQL中使用单引号 – 在这种情况下更容易:

 SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect FROM RussoundGeneral.dbo.Company c LEFT JOIN RussoundGeneral.dbo.CompanyMax cm ON (cm.companyId = c.companyId and cm.maxID is not null) WHERE CONTAINS ( companyName, '"BLAH "BLAHBLAH" Ltd.' ) GROUP BY c.companyID, c.companyName, c.dateAdded ORDER BY c.companyName ASC; 

使用双引号:

 SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect FROM RussoundGeneral.dbo.Company c LEFT JOIN RussoundGeneral.dbo.CompanyMax cm ON (cm.companyId = c.companyId and cm.maxID is not null) WHERE CONTAINS ( companyName, """BLAH ""BLAHBLAH"" Ltd." ) GROUP BY c.companyID, c.companyName, c.dateAdded ORDER BY c.companyName ASC; 

如果您使用编程语言构建字符串,那么您必须担心这些引号会超出编程语言中的字符串。 例如,如果您在C中构建字符串文字,则必须使用反斜杠转义双引号:

 static const char sql_stmt[] = "SELECT c.companyID, c.companyName, c.dateAdded,\n" " COUNT(cm.maxID) AS NumDirect\n" " FROM RussoundGeneral.dbo.Company c\n" " LEFT JOIN RussoundGeneral.dbo.CompanyMax cm\n" " ON (cm.companyId = c.companyId AND cm.maxID IS NOT NULL)\n" " WHERE CONTAINS(companyName, \"\"\"BLAH \"\"BLAHBLAH\"\" Ltd.\")\n" " GROUP BY c.companyID, c.companyName, c.dateAdded\n" " ORDER BY c.companyName ASC"; 

另一方面,如果您从用户那里读取数据 – 例如公司名称,那么您只需确保正确引用所读取的内容。

那些说“使用参数”的人是对的 – 它更容易,更可靠,更不容易受到SQL注入攻击(如果你还没有看到它,请参阅XKCD )。 但是,如果您了解基础知识,则可以适应系统的实际要求。

最后注意事项:在标准SQL中,双引号括起“分隔标识符”。 也就是说,双引号括起一个名称,必须将其视为数据库中某些内容的名称,而不是字符串文字。 在MS SQL Server中,[方括号]用于相同的目的; 括号之间的内容是列的名称或数据库内的任何内容。 许多系统比这更灵活; 并非所有系统在偏离标准方面都是相同的。

你试过用它的ASCII代码替换字符吗?

尝试使用escape关键字:

 SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect FROM RussoundGeneral.dbo.Company c LEFT JOIN RussoundGeneral.dbo.CompanyMax cm ON (cm.companyId = c.companyId and cm.maxID is not null ) WHERE CONTAINS ( companyName, '\"BLAH*' ) escape '\' group by c.companyID, c.companyName, c.dateAdded ORDER BY c.companyName ASC 

应该是这样的

 string sqlCommand = "SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect FROM RussoundGeneral.dbo.Company c LEFT JOIN RussoundGeneral.dbo.CompanyMax cm ON (cm.companyId = c.companyId and cm.maxID is not null ) WHERE CONTAINS ( companyName, '@strVal' ) group by c.companyID, c.companyName, c.dateAdded ORDER BY c.companyName ASC" SqlCommand command = new SqlCommand(strSQLCommand, conn); SqlCommand.Parameters.AddWithValue("@strval", SearchTextBox.Text); 

您最终必须从数据库中提取数据并将其显示在屏幕上或打印在报告上。 操纵双引号或任何额外的字符可能会变得非常混乱。

通过在INSERTS或UPDATES之前将字符串转换为HTML,您可以避免与引号管理相关的所有混淆。 在SELECT时,很容易从HTML转换回来。 在报告时(作为报告工具(如Crystal Reports)提出HTML格式化选项),您甚至不需要做任何事情来以正确的方式显示数据。

顺便说一句,不要忘记挂起发明这个公司名称的人。