可能重复:
T-SQL WHERE col IN (…)
SQL Server查询的最大大小是多少? (字符数)
IN子句的最大大小?我想我看到有关于Oracle有1000项限制的东西,但你可以用ANDing 2 INs来解决这个问题。 SQL Server中的类似问题?
更新 那么,如果我需要从另一个系统(非关系数据库)中获取1000个GUID并对SQL Server执行“JOIN in code”,那么最好的方法是什么?是否要向IN子句提交1000个GUID列表? 或者是否有其他技术可以更有效地工作?
我没有对此进行过测试,但我想知道是否可以将GUID作为XML文档提交。例如
<guids>
<guid>809674df-1c22-46eb-bf9a-33dc78beb44a</guid>
<guid>257f537f-9c6b-4f14-a90c-ee613b4287f3</guid>
</guids>
然后针对Doc和Table执行某种XQuery JOIN。效率低于1000项IN条款?
答案 0 :(得分:72)
每个SQL批处理必须符合Batch Size Limit:65,536 *网络数据包大小。
除此之外,您的查询受运行时条件的限制。它通常会耗尽堆栈大小,因为x IN(a,b,c)只是x = a OR x = b OR x = c,它创建一个类似于x = a OR的表达式树(x = b OR(x) = c)),因此大量的OR变得非常深。 SQL 7会命中SO at about 10k values in the IN,但是现在的堆栈更深(因为x64),所以它可以非常深。
<强>更新强>
您已经找到了Erland关于将列表/数组传递给SQL Server主题的文章。使用SQL 2008,您还可以Table Valued Parameters,它允许您将整个DataTable作为单个表类型参数传递并加入其中。
XML和XPath是另一种可行的解决方案:
SELECT ...
FROM Table
JOIN (
SELECT x.value(N'.',N'uniqueidentifier') as guid
FROM @values.nodes(N'/guids/guid') t(x)) as guids
ON Table.guid = guids.guid;
答案 1 :(得分:36)
公开了SQL Server最大值http://msdn.microsoft.com/en-us/library/ms143432.aspx(这是2008版本)
SQL查询可以是varchar(max),但显示为限制为65,536 *网络数据包大小,但即使这样,最有可能使您绊倒的是每个查询2100个参数。如果SQL选择参数化in子句中的文字值,我认为你会先达到这个限制,但我没有测试过。
编辑:测试它,即使在强制参数化下它幸存下来 - 我敲了一个快速测试并让它在In子句中执行30k项目。 (SQL Server 2005)
在10万件物品上花了一些时间然后掉了下来:
Msg 8623,Level 16,State 1,Line 1 查询处理器耗尽了内部资源,无法生成查询计划。这是一种罕见的事件,仅适用于引用大量表或分区的极其复杂的查询或查询。请简化查询。如果您认为自己错误地收到了此消息,请与客户支持服务部门联系以获取更多信息。
所以30k是可能的,但仅仅因为你可以做到 - 并不意味着你应该:)
编辑:由于其他问题而继续。
50k工作了,但是60k退出了,所以在我的测试台上的某个地方顺便说一下。
关于如何在不使用大的in子句的情况下连接值,我个人会创建一个临时表,将值插入到临时表中,对其进行索引然后在连接中使用它,给它优化联接的最佳机会。 (在临时表上生成索引将为其创建统计数据,这将有助于优化器作为一般规则,尽管1000 GUID不会完全找到非常有用的统计数据。)
答案 2 :(得分:12)
每批,65536 * Network Packet Size,这是4k,所以256 MB
但是,IN会在此之前停止,但这不准确。
您最终会遇到内存错误,但我无法回想起确切的错误。 无论如何,巨大的IN效率低下。
编辑:Remus提醒我:错误是关于“堆栈大小”
答案 3 :(得分:7)
您可以将GUID加载到临时表中,然后执行
... WHERE var IN SELECT guid FROM #scratchtable