简体   繁体   English

正确的字符串转义为T-SQL字符串文字

[英]Correct String Escaping for T-SQL string literals

I want to use a query as following, I am looking for exact information/link to escape strings 我想使用如下查询,我正在寻找转义字符串的确切信息/链接

BookTitle is NVARCHAR(200) BookTitle是NVARCHAR(200)

SELECT * FROM Books WHERE BookTitle IN ('Mars and Venus', 'Stack''s Overflow \\r\\n') SELECT * FROM Books WHERE BookTitle IN('Mars and Venus','Stack'的溢出\\ r \\ n')

Question: Does only "'" needs to be escaped or even \\r\\n needs to be escaped as well? 问题:是否只需要转义“'”,甚至还需要转义\\ r \\ n? MySql .Net Provider exposes a method to escape string values, is there any such function in Sql Server .Net Provider? MySql .Net Provider公开了一个转义字符串值的方法,Sql Server .Net Provider中是否有这样的函数?

I probably need C# equivalent escaping for string values. 我可能需要C#等效转义为字符串值。

I am aware of Parameterized Command, but in order to minimize my server to client communication, and my values in IN clause are in number from 20 to 50, it becomes too much network expensive to run SELECTs for each value of BookTitle in one call. 我知道参数化命令,但是为了最小化我的服务器到客户端的通信,并且IN子句中的值在20到50之间,在一次调用中为BookTitle的每个值运行SELECT会变得太昂贵。 Rather running single query and returning all results cascaded helps saving network resources. 而是运行单个查询并返回所有级联结果有助于节省网络资源。

SQL Server won't recognise the \\r\\n sequence, whether it's escaped or not. SQL Server无法识别\\r\\n序列,无论它是否被转义。

You'll need to do something like this instead if you want to match the \\r\\n in BookTitle : 如果你想匹配BookTitle中的\\r\\n ,你需要做这样的事情:

-- \r = CHAR(13)
-- \n = CHAR(10)
SELECT *
FROM Books
WHERE BookTitle IN ('Mars and Venus', 'Stack''s Overflow ' + CHAR(13) + CHAR(10))

There are more things that have to be escaped than just quotes or new line characters. 除了引号或换行符之外,还有许多事情需要转义。 What if there's a binary input (by hacker)? 如果有二进制输入(由黑客)怎么办? Better use PreparedStatement (in java) or any other equivalent in the target language. 最好使用PreparedStatement(在java中)或目标语言中的任何其他等效语句。 Java sample: Java示例:

PreparedStatement ps = con.prepareStatement("SELECT * FROM Books WHERE BookTitle IN (?, ?)");
ps.setString(1, "Mars and Venus");
ps.setString(2, "Stack's Overflow
and 
");

ResultSet rs = ps.executeQuery();
....

I've run into a similar problem, where I needed to have a IN in my select query, and the number of elements varied at run time. 我遇到了类似的问题,我需要在我的选择查询中使用IN,并且元素的数量在运行时变化。

I use a parameterized query in the form of a stored procedure and pass in a delimited string containing the list of things I'm looking for. 我以存储过程的形式使用参数化查询,并传入包含我正在寻找的事物列表的分隔字符串。 The escaping is automatically handled by the system, no need to take extraordinary steps. 转义由系统自动处理,无需采取特殊步骤。 Better not make it delimited by characters that will be found in the text you're searching (like commas). 最好不要在你正在搜索的文本中找到的字符(如逗号)分隔。 a vertical bar ("|") would probably work best in many cases. 在许多情况下,垂直条(“|”)可能效果最好。

By the way, make sure the CRLFs in your table are CHAR(13)+CHAR(10) because the opposite way around isn't \\r\\n and you wouldn't find it if Environment.NewLine was part of your search. 顺便说一句,确保表中的CRLF是CHAR(13)+ CHAR(10),因为相反的方式不是\\ r \\ n,如果Environment.NewLine是搜索的一部分,你就找不到它。

Here's a stored procedure using a quick and dirty parse resolving to a table that I have used: 这是一个存储过程,使用快速和脏解析解析为我使用过的表:

CREATE PROCEDURE FindBooks
(
    @list varchar(500)
)
AS

CREATE TABLE #parse_table (item varchar(500))

DECLARE @temp                       VARCHAR(500)
DECLARE @result                     VARCHAR(500)
DECLARE @str                        VARCHAR(500)
DECLARE @pos                        SMALLINT

SET @temp = RTRIM(LTRIM(@list))
SET @pos = 1

WHILE @pos > 0
    BEGIN
    SET @pos = CHARINDEX('|',@temp)
    IF @pos > 0 
       BEGIN
         SET @result = SUBSTRING(@temp,1,@pos - 1)
         SET @temp = RTRIM(LTRIM(SUBSTRING(@temp,@pos+1,LEN(@temp) - @pos)))

         INSERT INTO #parse_table
     SELECT @result
       END
    ELSE
       INSERT INTO #parse_table
       SELECT @temp
END

SELECT * FROM Books WHERE Title in (select * from #parse_table)

Simply create your list of book titles as a simple string (containing whatever embedded apostrophes, CRLFs, and so on) and use a parameterized query. 只需将书名列表创建为一个简单的字符串(包含任何嵌入的撇号,CRLF等)并使用参数化查询。 Of course, your stored proc can contain other things besides the delimited list. 当然,您的存储过程可以包含除分隔列表之外的其他内容。

You could use table value parameters to pass in the the values for your IN statement. 您可以使用表值参数传入IN语句的值。 If you are not using a new enough version of visual studio and/or sql server to have access to table value parameters, you can instead pass in one comma separated list as string parameter, and then parse the the parameter into a table. 如果您没有使用足够新版本的visual studio和/或sql server来访问表值参数,则可以将一个以逗号分隔的列表作为字符串参数传入,然后将该参数解析为表。 There are several methods to split strings into a temp table/table variable. 有几种方法可以将字符串拆分为临时表/表变量。 You can google "split function in sql server" for several options. 你可以谷歌“在SQL服务器中拆分功能”的几个选项。

Usually what I'd do for situations like this, is pass your information in as a parameter, but in XML, so you can do something like this: 通常我在这种情况下所做的是将您的信息作为参数传递,但是在XML中,您可以执行以下操作:

DECLARE @iDoc INT
EXEC sp_xml_preparedocument @iDoc OUTPUT, @MyXml

SELECT
    *
FROM
    MyTable
WHERE
    MyColumn IN (SELECT [Id] FROM OPENXML(@iDoc,'/ss/s',2) WITH ([Id] INT '.'))

EXEC sp_xml_removedocument @iDoc

in this case, the xml would look like '<ss><s>1</s><s>2</s>...etc...</ss>' 在这种情况下,xml看起来像'<ss><s>1</s><s>2</s>...etc...</ss>'

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

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