76

I'm using the following code:

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

However, if I put more than ~3000 numbers in the IN clause, SQL throws an error.

Does anyone know if there's a size limit or anything similar?!!

Jesse
  • 8,605
  • 7
  • 47
  • 57
jDeveloper
  • 2,096
  • 2
  • 21
  • 27
  • 2
    Split the numbers in the IN clause up by groups large enough to process, and async them all at the same time. – Travis J Dec 01 '14 at 23:39
  • Actaully do not use in - IN is bad because it contains no statistical information. Declare a table valued type of the keys with a primary key (then it has statistical values attached), insert the values there, JOIN between table and that temp table and the query optimizer can do it's work. – TomTom Feb 28 '20 at 20:43

9 Answers9

73

Depending on the database engine you are using, there can be limits on the length of an instruction.

SQL Server has a very large limit:

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

ORACLE has a very easy to reach limit on the other side.

So, for large IN clauses, it's better to create a temp table, insert the values and do a JOIN. It works faster also.

xanadont
  • 7,493
  • 6
  • 36
  • 49
tekBlues
  • 5,745
  • 1
  • 29
  • 32
  • 5
    not correct. Max size of SQL instruction or a batch is 65K * (network packet size which is usually 4K) = more then 250 Mb... http://msdn.microsoft.com/en-us/library/ms143432.aspx . – Bogdan_Ch Jul 01 '09 at 14:43
  • 1
    You are damned right on the spot, I complemented the answer. BTW, in ORACLE the limit is VERY easy to reach!. – tekBlues Jul 01 '09 at 14:50
  • According to the forum its not faster in the case of SQLite: http://sqlite.1065341.n5.nabble.com/Is-there-a-limit-for-the-number-of-items-in-an-IN-clause-td81307.html – wobbily_col Apr 16 '20 at 13:05
37

There is a limit, but you can split your values into separate blocks of in()

Select * 
From table 
Where Col IN (123,123,222,....)
or Col IN (456,878,888,....)
Iain Hoult
  • 3,889
  • 5
  • 25
  • 39
13

Parameterize the query and pass the ids in using a Table Valued Parameter.

For example, define the following type:

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

Along with the following stored procedure:

CREATE PROCEDURE sp__Procedure_Name
    @OrderIDs IdTable READONLY,
AS

    SELECT *
    FROM table
    WHERE Col IN (SELECT Id FROM @OrderIDs)
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
Greg
  • 23,155
  • 11
  • 57
  • 79
  • 2
    I don't know why you are being downvoted because this is a completely valid solution. Although I'd change the `Select Id FROM @OrderIDs` to a join. – ldam Jul 05 '16 at 08:37
  • i know this is an old answer, but do you know what happens to your OrderIds? does it remain? or is it simple a temp file? – Jason V Jul 26 '17 at 15:26
  • 1
    @Jason `@OrderIds` is a table-valued parameter. It only exists for the duration of the procedure. – Greg Jul 26 '17 at 15:34
  • This is my goto solution. Works well called from javascript, C#. The SQL statement ends up containing multiple INSERTs to the table type instance before the query. – cloudsafe Jul 14 '21 at 12:47
5

Why not do a where IN a sub-select...

Pre-query into a temp table or something...

CREATE TABLE SomeTempTable AS
    SELECT YourColumn
    FROM SomeTable
    WHERE UserPickedMultipleRecordsFromSomeListOrSomething

then...

SELECT * FROM OtherTable
WHERE YourColumn IN ( SELECT YourColumn FROM SomeTempTable )
Jesse
  • 8,605
  • 7
  • 47
  • 57
DRapp
  • 47,638
  • 12
  • 72
  • 142
4

Depending on your version, use a table valued parameter in 2008, or some approach described here:

Arrays and Lists in SQL Server 2005

A-K
  • 16,804
  • 8
  • 54
  • 74
1

For MS SQL 2016, passing ints into the in, it looks like it can handle close to 38,000 records.

select * from user where userId in (1,2,3,etc)
roncansan
  • 2,310
  • 6
  • 27
  • 34
0

You did not specify the database engine in question; in Oracle, an option is to use tuples like this:

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

This ugly hack only works in Oracle SQL, see https://asktom.oracle.com/pls/asktom/asktom.search?tag=limit-and-conversion-very-long-in-list-where-x-in#9538075800346844400

However, a much better option is to use stored procedures and pass the values as an array.

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
ENOTTY
  • 394
  • 5
  • 18
0

I solved this by simply using ranges

WHERE Col >= 123 AND Col <= 10000

then removed unwanted records in the specified range by looping in the application code. It worked well for me because I was looping the record anyway and ignoring couple of thousand records didn't make any difference.

Of course, this is not a universal solution but it could work for situation if most values within min and max are required.

TriCore
  • 1,844
  • 1
  • 16
  • 17
-4

You can use tuples like this: SELECT * FROM table WHERE (Col, 1) IN ((123,1),(123,1),(222,1),....)

There are no restrictions on number of these. It compares pairs.

Lukasz
  • 1
  • No, in SQL Server you can not. SQL Server uses T-SQL which is not ANSI SQL compliant (neither is any other dialect). – TT. Oct 10 '17 at 07:47
  • This ugly hack only works in Oracle SQL, see https://asktom.oracle.com/pls/asktom/asktom.search?tag=limit-and-conversion-very-long-in-list-where-x-in#9538075800346844400 – ENOTTY Jan 23 '19 at 09:22