2008-12-22 98 views
2

我最近已经增加了一个国际化的公司,它被命名为“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 
+0

请示例SQL代码? – 2008-12-22 20:09:09

回答

6

不幸的是,双引号在FTI内部有特殊的含义,所以即使你参数化了它,FTI引擎也会将它视为短语分隔符。我不确定是否有简单的方法在FTI搜索中加入双引号。括号也是一种特殊字符,但可以用引号括起来作为查询词 - 但不包括AFAIK双引号。

更新

搜索的一点建议,加倍报价为“”可以解决这个问题 - 值得一试。就个人而言,我会在数据库中执行此操作,因为这是TSQL实现细节。

同样地,“需要翻番才能‘(完全独立于TSQL逃逸)之前传递给FTI’,

+2

T-SQL中的字符串操作速度令人难以置信。如果查询被调用了很多,最好在调用之前修改数据库外部的引号。 – 2008-12-24 21:24:29

3

我强烈怀疑你是动态生成SQL - 例如

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

这是有很多原因一个非常,非常糟糕的主意 - 尤其是SQL injection attacks。改为使用参数化的SQL语句,而不是单独指定参数。

请看sql-injection tag问题的各种答案,以了解如何正确执行此操作的示例。

+1

对不起,但没有。 concatinated数据库会让你在这里被俗语殴打.....被我。我不会强迫他们。 – Russ 2008-12-22 20:14:57

7

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

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

0

你试图取代它的ASCII码字符?

0

尝试使用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 
0

应该像

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);
1

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

在标准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中,[方括号]用于相同的目的;括号之间是什么是列或数据库内的任何内容的名称。许多系统比这更灵活;并不是所有的系统在偏离标准方面都是一样的。

0

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

通过转换你的字符串插入或更新,你是避免全挂报价管理混乱之前为HTML。在SELECT时间,从HTML转换回来很容易。在报告时间(因为报表工具(如Crystal Reports)提出了一种HTML格式选项),您甚至不必采取任何措施以正确的方式显示数据。

顺便说一下,不要忘记挂上发明这个公司名称的家伙。