2

给定一张像

CREATE TABLE [dbo].[Article](
    [Id] [int] NOT NULL,
    [CategoryId] [int] NOT NULL,
    [Text] [nchar](10) NOT NULL)

允许用户选择他们想要查看数据的一个或多个类别。通常他们会选择 1-20 个类别。为了适应这种情况,我生成类似于以下内容的参数化查询:

SELECT * FROM Article
WHERE CategoryId IN (@c1, @c2, @c3, @c4, @c5)

但是,在一些罕见的用例中,用户可以合法地选择数百个类别。这使我发现了 Linq-to-Entities 的局限性,我通过形成类别代码范围来解决这个问题。不幸的是,这只会解决问题,因为可以传递给 SQL Server 的查询的大小是有限制的。

我想重构这个查询以避免任何硬限制。我的第一个想法是创建一个包含所请求类别的临时表,并对该临时表执行内部连接来代替IN(...)子句。但是,我知道临时表可能会很慢。

有没有更优雅和/或性能更好的解决方案来解决这个问题?

4

2 回答 2

1

您的第一直觉是正确的,尽管您可能会发现一个足以代替临时表的表值变量。不要担心这种情况下的性能;这不会很重要。如果需要,总是可以在临时表上创建索引,但这似乎不太可能。CategoryId 字段是否有索引?

于 2013-02-28T22:38:40.027 回答
1

编辑:

哎呀。我错过了 Linq 部分。

这是一种可能值得一试的替代语法(出于性能原因,而不是出于字符串长度原因)

Select * from dbo.Article art where exists ( select null from ( select 0 as MyV union all select 2 as MyV union all select 3 as MyV ) as derived1 where derived1.MyV = art.CategoryId )

……………………………………………………………………………………………………………………

这就是我的处理方式。

有时我的变量表更改为#temp 表。我测试了两种不同的性能场景。

您可以通过 xml 传递尽可能多或尽可能少的值。

DECLARE @input XML = '<root>
  <category myvalue="1" />
  <category myvalue="2" />
  <category myvalue="3" />
</root>'



declare @holder table ( CatID int )
Insert into @holder (CatID)
SELECT
    myvalue = MyXmlTable.value('(@myvalue)', 'int')
FROM
    @input.nodes('/root/category') AS Tbl(MyXmlTable)


select * from @holder    

SELECT * FROM Article art
where exists (select null from @holder hold where hold.CatID = art.CategoryId

更大的写在这里:

http://www.sqlservercentral.com/articles/Stored+Procedures/thezerotonparameterproblem/2283/

于 2013-02-28T22:42:06.247 回答