【问题标题】:Limit on the WHERE col IN (...) condition限制 WHERE col IN (...) 条件
【发布时间】:2010-11-07 08:27:04
【问题描述】:

我正在使用以下代码:

SELECT * FROM table
WHERE Col IN (123,123,222,....)

但是,如果我在 IN 子句中输入超过 ~3000 个数字,SQL 会引发错误。

有没有人知道是否有大小限制或类似的东西?!!

【问题讨论】:

  • 将 IN 子句中的数字按足够大的组进行处理,并同时将它们全部异步。
  • 实际上不要使用 in - IN 不好,因为它不包含统计信息。使用主键声明键的表值类型(然后附加统计值),在此处插入值,在表和该临时表之间连接,查询优化器可以完成它的工作。

标签: sql sql-server tsql


【解决方案1】:

根据您使用的数据库引擎,指令的长度可能有所限制。

SQL Server 的限制非常大:

http://msdn.microsoft.com/en-us/library/ms143432.aspx

ORACLE 在另一边有一个非常容易达到的极限。

因此,对于大型 IN 子句,最好创建一个临时表,插入值并执行 JOIN。它的工作速度也更快。

【讨论】:

【解决方案2】:

有一个限制,但您可以将值拆分为单独的 in() 块

Select * 
From table 
Where Col IN (123,123,222,....)
or Col IN (456,878,888,....)

【讨论】:

  • IN() 不是 SARGable。最好将参数推送到临时表或 TVP 中,然后使用 INNER JOIN。
  • 上述查询有什么限制?我的意思是我可以用 OR 定义多少个 IN 子句?
  • @MichaelK.Campbell 你能提供一些关于“IN() is not SARGable”的链接吗?它有多重要?性能会下降 200%?
  • @Woland 这里是wiki 关于sargable
【解决方案3】:

为什么不做一个 where IN 一个子选择...

预查询到临时表或其他东西...

CREATE TABLE SomeTempTable AS
    SELECT YourColumn
    FROM SomeTable
    WHERE UserPickedMultipleRecordsFromSomeListOrSomething

那么……

SELECT * FROM OtherTable
WHERE YourColumn IN ( SELECT YourColumn FROM SomeTempTable )

【讨论】:

  • 加入临时表比通常的子选择要好。
  • exists 子句会不会更好?
【解决方案4】:

根据您的版本,在 2008 年使用表值参数,或此处描述的某种方法:

Arrays and Lists in SQL Server 2005

【讨论】:

    【解决方案5】:

    参数化查询并使用Table Valued Parameter 传递ID。

    例如,定义如下类型:

    CREATE TYPE IdTable AS TABLE (Id INT NOT NULL PRIMARY KEY)
    

    连同以下存储过程:

    CREATE PROCEDURE sp__Procedure_Name
        @OrderIDs IdTable READONLY,
    AS
    
        SELECT *
        FROM table
        WHERE Col IN (SELECT Id FROM @OrderIDs)
    

    【讨论】:

    • 我不知道您为什么被否决,因为这是一个完全有效的解决方案。虽然我会将Select Id FROM @OrderIDs 更改为加入。
    • 我知道这是一个旧答案,但您知道您的 OrderId 会发生什么吗?它仍然存在吗?还是简单的临时文件?
    • @Jason @OrderIds 是一个表值参数。它仅在手术期间存在。
    • 这是我的 goto 解决方案。从 javascript、C# 调用效果很好。 SQL 语句最终在查询之前包含对表类型实例的多个 INSERT。
    【解决方案6】:

    你可以像这样使用元组: 选择 * 从表 WHERE (Col, 1) IN ((123,1),(123,1),(222,1),....)

    这些数量没有限制。它比较对。

    【讨论】:

    • 不,在 SQL Server 中你不能。 SQL Server 使用不符合 ANSI SQL 的 T-SQL(也不符合任何其他方言)。
    • 这个丑陋的hack只适用于Oracle SQL,见asktom.oracle.com/pls/asktom/…
    【解决方案7】:

    您没有指定有问题的数据库引擎;在 Oracle 中,一个选项是使用这样的元组:

    SELECT * FROM table
    WHERE (Col, 1) IN ((123,1),(123,1),(222,1),....)
    

    这个丑陋的 hack 只适用于 Oracle SQL,见 https://asktom.oracle.com/pls/asktom/asktom.search?tag=limit-and-conversion-very-long-in-list-where-x-in#9538075800346844400

    但是,更好的选择是使用存储过程并将值作为数组传递。

    【讨论】:

      【解决方案8】:

      对于 MS SQL 2016,将 int 传递到 in,看起来它可以处理接近 38,000 条记录。

      select * from user where userId in (1,2,3,etc)
      

      【讨论】:

      • value过大会出现什么错误?
      【解决方案9】:

      我通过简单地使用范围解决了这个问题

      WHERE Col >= 123 AND Col <= 10000
      

      然后通过在应用程序代码中循环删除指定范围内不需要的记录。它对我来说效果很好,因为无论如何我都在循环记录并且忽略几千条记录并没有任何区别。

      当然,这不是一个通用的解决方案,但如果需要 min 和 max 内的大多数值,它可能适用于这种情况。

      【讨论】:

        猜你喜欢
        • 2011-05-15
        • 2016-10-14
        • 1970-01-01
        • 1970-01-01
        • 2011-01-10
        • 2018-10-27
        • 2019-12-13
        • 2019-05-12
        • 2011-02-15
        相关资源
        最近更新 更多