简体   繁体   English

SQL 2005/2008中的转义双引号

[英]Escape double quotes in SQL 2005/2008

I have an international company that has recently been added, which is named "BLA "BLAHBLAH" Ltd. (The double quotes are part of the name. ) 我有一家最近加入的国际公司,名为“ BLA“ BLAHBLAH”Ltd。(双引号是名称的一部分。)

Whenever a user tries to search for this company, by entering "Blah, or something to that affect, the search fails with a syntax error in SQL server. 每当用户尝试通过输入“ Blah或与此相关的内容”来搜索该公司时,搜索都会失败,并在SQL Server中出现语法错误。

How can I escape this so the search will not fail? 我如何才能避免这种情况,以使搜索不会失败?

Sample SQL: 示例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

Use a parameterized query and all your quoting woes will be gone. 使用参数化查询,您所有的报价麻烦都将消失。

Edit: If you're not letting them enter more than one word in the CONTAINS, sanitize the parameter by removing the quotes. 编辑:如果不让他们在CONTAINS中输入多个单词,请通过删除引号对参数进行清理。 Sanitizing the input by removing the quotes may work anyhow, regardless of the multi-word search. 无论多词搜索如何,通过删除引号对输入内容进行消毒都可能起作用。

Unfortunately, double-quotes have special meaning inside FTI, so even if you parameterize it, the FTI engine treats it as a phrase delimiter. 不幸的是,双引号在FTI中具有特殊的含义,因此即使您将其参数化,FTI引擎也会将其视为短语定界符。 I am not sure there is an easy way to include double-quotes in an FTI search. 我不确定是否有简单的方法可以在FTI搜索中包含双引号。 Brackets are also a special character, but can be encased in quotes to treat as a query term - but not AFAIK double-quotes. 括号也是一个特殊字符,但是可以将其括在引号中,以将其视为查询字词,但不能将AFAIK双引号括起来。

Update 更新资料

A bit of searching suggests that doubling the quote to "" may fix it - worth a try. 一些搜索表明,将引号加倍到“”可能会解决问题-值得一试。 Personally, I'd do this inside the DB, since this is a TSQL implementation detail. 就个人而言,我将在数据库内部执行此操作,因为这是TSQL实现的详细信息。

Likewise, ' needs to be doubled to '' before passing to FTI (completely separate to TSQL escaping), 同样,在传递给FTI(与TSQL转义完全分开)之前,需要将“加倍到”。

I strongly suspect you're building the SQL dynamically - eg 我强烈怀疑您正在动态构建SQL-例如

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

That's a really, really bad idea for many reasons - most notably SQL injection attacks . 由于很多原因,这是一个非常非常糟糕的主意-最著名的是SQL注入攻击 Use parameterised SQL statements instead, where you specify the parameters separately. 而是使用参数化的SQL语句,在此您分别指定参数。

Look at various answers to questions with the sql-injection tag for examples of how to do this properly. 使用sql-injection标记查看各种问题的答案,以获取有关如何正确执行此操作的示例。

This is a bit of a theoretical answer, but maybe it will help. 这是一个理论上的答案,但也许会有所帮助。 The short version is "use parameters in the query", but it helps to understand the full details. 简短的版本是“在查询中使用参数”,但是它有助于理解完整的细节。

In standard SQL, strings are enclosed in single quotes, and embedded single quotes are represented by two single quotes in a row: 在标准SQL中,字符串用单引号引起来,而嵌入式单引号则用一行中的两个单引号表示:

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

In some dialects of SQL, you can instead close strings in double quotes; 在SQL的某些方言中,您可以改为将双引号括起来的字符串。 you then need to double the double quotes to embed a single instance of a double quote: 然后,您需要将双引号加倍以嵌入双引号的单个实例:

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

It isn't clear from the question whether the company name includes the outer double quotes as well as the middle one, or if it just contains the middle one. 从这个问题尚不清楚,公司名称是否包含外部双引号和中间双引号,或者仅包含中间双引号。 However, in principle, the rules are the same. 但是,原则上规则是相同的。 Assuming all three double quotes are required, and using single quotes in the SQL - much easier in this context: 假设所有三个双引号都是必需的,并且在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;

Using double quotes: 使用双引号:

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;

If you are building strings in a programming language, then you have to worry about getting these quotes past whatever evaluates strings in your programming language. 如果要使用编程语言构建字符串,则必须担心使这些引号超出通过编程语言评估字符串的范围。 For example, if you were building a string literal in C, you'd have to escape the double quotes with backslashes: 例如,如果要在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";

On the other hand, if you read the data from the user - such as the company name, then you simply have to ensure what is read is correctly quoted. 另一方面,如果您从用户那里读取数据(例如公司名称),则只需确保正确读取引用的内容即可。

Those who said "use parameters" are right - it is much easier and more reliable and less vulnerable to SQL injection attacks (see XKCD if you haven't already see it). 那些说“使用参数”的人是正确的-它更容易,更可靠,更不容易受到SQL注入攻击(如果尚未看到,请参阅XKCD )。 But if you understand the fundamentals, you can adapt to the actual requirements of your system. 但是,如果您了解基础知识,则可以适应系统的实际需求。

Final note: in standard SQL, double quotes enclose 'delimited identifiers'. 最后说明:在标准SQL中,双引号括起“定界标识符”。 That is, the double quotes surround a name which must be treated as the name of something in the database, not as a string literal. 也就是说,双引号括起一个名称,该名称必须被视为数据库中某物的名称,而不是字符串文字。 In MS SQL Server, the [square brackets] serve the same purpose; 在MS SQL Server中,[方括号]具有相同的作用; what is between the brackets is the name of a column or whatever inside the database. 方括号之间是列名或数据库内部的名称。 Many systems are more flexible than that; 许多系统比这更灵活。 not all systems are the same in how they deviate from the standard. 并非所有系统在偏离标准方面都相同。

您是否尝试过用ASCII码替换字符?

Try Using the escape keyword: 尝试使用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

should be something like 应该是这样的

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

You will finally have to extract data from your database and have it displayed on screen or printed on reports. 您最终将不得不从数据库中提取数据,并将其显示在屏幕上或打印在报告上。 Manipulating double quotes or any extra character can then become very confusing. 然后,使用双引号或任何其他字符会变得非常混乱。

By converting your strings to HTML before INSERTS or UPDATES, you are avoiding all the confusion linked to quotes management. 通过在INSERTS或UPDATES之前将字符串转换为HTML,可以避免与报价管理相关的所有混乱。 At SELECT time, it will be easy to convert back from HTML. 在SELECT时,很容易从HTML转换回来。 At reporting time (as reporting tools (such as Crystal Reports) propose an HTML formatting option), you will not even have to do anything to display data in a correct way. 在报告时(由于报告工具(例如Crystal Reports)提出了HTML格式设置选项),您甚至无需执行任何操作即可以正确的方式显示数据。

By the way, do not forget to hang the guy that invented this company name. 顺便说一句,别忘了挂上发明这个公司名称的家伙。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM