给出像
这样的表格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的局限性,我通过形成ranges of category codes来解决这个问题。不幸的是,这只会推迟问题,因为可以传递给SQL Server的查询大小有限。
我想重构此查询以避免任何硬限制。我的第一个想法是创建一个包含所请求类别的临时表,并对该临时表执行内部联接以代替IN(...)
子句。但是,我知道临时表可能很慢。
这个问题是否有更优雅和/或性能更好的解决方案?
答案 0 :(得分:1)
你的第一直觉是正确的,你可能会发现一个表值变量足以取代临时表。在这样的情况下,不要担心性能;它不会很重要。如果需要,可以始终在临时表上创建索引,但这似乎是不可能的。 CategoryId字段是否有索引?
答案 1 :(得分: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表。我测试了2种不同的性能方案。
您可以通过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/