逃生在SQL双引号2005/2008
我最近已经增加了一个国际化的公司,它被命名为“BLA‘BLAHBLAH’有限责任公司(双引号是名称的一部分。)逃生在SQL双引号2005/2008
每当用户尝试搜索这家公司,通过输入“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实现细节。
同样地,“需要翻番才能‘(完全独立于TSQL逃逸)之前传递给FTI’,
T-SQL中的字符串操作速度令人难以置信。如果查询被调用了很多,最好在调用之前修改数据库外部的引号。 – 2008-12-24 21:24:29
我强烈怀疑你是动态生成SQL - 例如
// Bad code, do not use!
string sql = "SELECT * FROM Foo WHERE X LIKE '" + input + "%'";
这是有很多原因一个非常,非常糟糕的主意 - 尤其是SQL injection attacks。改为使用参数化的SQL语句,而不是单独指定参数。
请看sql-injection tag问题的各种答案,以了解如何正确执行此操作的示例。
对不起,但没有。 concatinated数据库会让你在这里被俗语殴打.....被我。我不会强迫他们。 – Russ 2008-12-22 20:14:57
使用参数化查询,所有引用的问题都将消失。
编辑:如果您不让他们在CONTAINS中输入多个单词,请删除引号以清除参数。无论多字搜索如何,通过删除引号来消除输入可能无论如何都有效。
你试图取代它的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);
这是一个有点理论的答案,但也许会有所帮助。简短版本是“在查询中使用参数”,但它有助于理解全部细节。
在标准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中,[方括号]用于相同的目的;括号之间是什么是列或数据库内的任何内容的名称。许多系统比这更灵活;并不是所有的系统在偏离标准方面都是一样的。
您最终必须从数据库中提取数据,并将其显示在屏幕上或打印在报告中。操纵双引号或任何额外字符可能会变得非常混乱。
通过转换你的字符串插入或更新,你是避免全挂报价管理混乱之前为HTML。在SELECT时间,从HTML转换回来很容易。在报告时间(因为报表工具(如Crystal Reports)提出了一种HTML格式选项),您甚至不必采取任何措施以正确的方式显示数据。
顺便说一下,不要忘记挂上发明这个公司名称的家伙。
请示例SQL代码? – 2008-12-22 20:09:09