簡體   English   中英

參數化的Sql查詢

[英]Parameterized Sql queries

這是我現在開裂的堅果

我正在開發的應用程序有一些針對SQL的高級處理。 其中一個操作根據集合中的項目名稱從不同的表中選擇當前上下文中的對象的各種元數據。 為此,執行一系列“select ... from ... where ... in()”,並且為了防止惡意SQL代碼,Sql參數用於構造“in()”子句的內容。

但是,當用於構造“in()”子句的項集合大於2100項時,由於每個查詢的Sql Server限制了max 2100 Sql參數,因此失敗。

我現在嘗試的一種方法是創建一個#temp表來存儲所有項目名稱,然后在原始查詢中加入表格,而不是使用“where in()”。 這讓我對如何使用.NET代碼中存儲在數組中的項名稱填充表格感到頭疼。 當然,必須有一些批量方式來插入所有內容而不是為每個項目單獨發布“插入”?

除此之外,我對解決這個問題的替代方法非常感興趣。

非常感謝

一種可能的解決方法是使用查詢XML的功能,並簡單地將“in”的所有數據作為xml列發送,然后加入其中。

可以使用相同的方法來填充臨時表,但是,為什么不直接使用它。

這是一個簡短的示例,應該說明:

declare @wanted xml
set @wanted = '<ids><id>1</id><id>2</id></ids>'
select * 
from (select 1 Id union all select 3) SourceTable 
where Id in(select Id.value('.', 'int') from @wanted.nodes('/ids/id') as Foo(Id))

只需在應用程序中構建xml並將其作為參數傳遞。

Hrm,在不知道上下文和更多關於數據以及您如何使用結果和性能問題的情況下,我將嘗試提出一個替代方案。 你可以分成多個查詢嗎? 與現在一樣,但不是在項目中使用2100+構建查詢,而是在每個項目中構建兩個1050,然后合並結果。

預防惡意SQL代碼:>使用存儲過程。

是的,SQL Server 2005有一個批量插入: http//msdn.microsoft.com/en-us/library/ms188365.aspx

您可以使用.NET 2.0引入的SqlBulkCopy類。 它實際上非常簡單易用。 看看這個:

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

對於批量更新問題:請查看包含數據表的數據適配器。 您可以設置一個參數,允許您批量插入/更新表中的項目,並且您可以在批處理MSDN文章中選擇項目的nr

您似乎應該仔細查看業務問題或域,以確定更好的方法來過濾查詢中的項目。 IN()子句可能不是您執行此操作的最佳方式。 也許在您的情況下,添加數據類別或過濾器而不是要包含的大項目列表會更好。 在不了解業務問題/背景的情況下,很難說。

好吧,我不確定這對你有多好或者性能如何,但是這里有一些代碼我過去用來實現類似的:

    CREATE FUNCTION [dbo].[Split](
    @list ntext
)
RETURNS @tbl TABLE (listpos int IDENTITY(1, 1) NOT NULL,
                          number  int NOT NULL) 
AS
BEGIN
    DECLARE @pos      int,
            @textpos  int,
            @chunklen smallint,
            @str      nvarchar(4000),
            @tmpstr   nvarchar(4000),
            @leftover nvarchar(4000)

    SET @textpos = 1
    SET @leftover = ''
    WHILE @textpos <= datalength(@list) / 2
    BEGIN
       SET @chunklen = 4000 - datalength(@leftover) / 2
       SET @tmpstr = ltrim(@leftover + substring(@list, @textpos, @chunklen))
       SET @textpos = @textpos + @chunklen

       SET @pos = charindex(',', @tmpstr)
       WHILE @pos > 0
       BEGIN
          SET @str = substring(@tmpstr, 1, @pos - 1)
          INSERT @tbl (number) VALUES(convert(int, @str))
          SET @tmpstr = ltrim(substring(@tmpstr, @pos + 1, len(@tmpstr)))
          SET @pos = charindex(',', @tmpstr)
       END

       SET @leftover = @tmpstr
    END

    IF ltrim(rtrim(@leftover)) <> ''
       INSERT @tbl (number) VALUES(convert(int, @leftover))

    RETURN
END

然后在您的其他存儲過程中,您可以傳入逗號分隔的ID字符串,例如:

select a.number from split('1,2,3') a inner join myothertable b on a.number = b.ID

就像我說的那樣,這可能真的很糟糕,因為它包含了大量的字符串操作,而且我不記得我從哪里獲得了這個功能......但它可以用來挑選......

我想如果你真的不需要索引原始字符串,你也可以去除填充listpos列的位。

SQL Server 2008將具有表參數。 這是你想要的錘子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM