IN clause limitation in Sql Server
Yes, there is a limit, but Microsoft only specifies that it lies "in the thousands":
Explicitly including an extremely large number of values (many thousands of values separated by commas) within the parentheses, in an IN clause can consume resources and return errors 8623 or 8632. To work around this problem, store the items in the IN list in a table, and use a SELECT subquery within an IN clause.
Looking at those errors in details, we see that this limit is not specific to IN
but applies to query complexity in general:
Error 8623:
The query processor ran out of internal resources and could not produce a query plan. This is a rare event and only expected for extremely complex queries or queries that reference a very large number of tables or partitions. Please simplify the query. If you believe you have received this message in error, contact Customer Support Services for more information.
Error 8632:
Internal error: An expression services limit has been reached. Please look for potentially complex expressions in your query, and try to simplify them.
Maximum size for a SQL Server Query? IN clause? Is there a Better Approach
Every SQL batch has to fit in the Batch Size Limit: 65,536 * Network Packet Size.
Other than that, your query is limited by runtime conditions. It will usually run out of stack size because x IN (a,b,c) is nothing but x=a OR x=b OR x=c which creates an expression tree similar to x=a OR (x=b OR (x=c)), so it gets very deep with a large number of OR. SQL 7 would hit a SO at about 10k values in the IN, but nowdays stacks are much deeper (because of x64), so it can go pretty deep.
Update
You already found Erland's article on the topic of passing lists/arrays to SQL Server. With SQL 2008 you also have Table Valued Parameters which allow you to pass an entire DataTable as a single table type parameter and join on it.
XML and XPath is another viable solution:
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;
Limit to number of Items in list for WHERE clause SQL query
Explicitly including an extremely large number of values (many thousands of values separated by commas) within the parentheses, in an IN clause can consume resources and return errors 8623 or 8632. To work around this problem, store the items in the IN list in a table, and use a SELECT subquery within an IN clause.
Error 8623:
The query processor ran out of internal resources and could not
produce a query plan. This is a rare event and only expected for
extremely complex queries or queries that reference a very large
number of tables or partitions. Please simplify the query. If you
believe you have received this message in error, contact Customer
Support Services for more information.Error 8632:
Internal error: An expression services limit has been reached. Please
look for potentially complex expressions in your query, and try to
simplify them.
microsoft docs
Limit on the WHERE col IN (...) condition
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.
SQL IN Clause 1000 item limit
You should transform the IN clauses to INNER JOIN clauses.
You can transform a query like this one
SELECT foo
FROM bar
WHERE bar.stuff IN
(SELECT stuff FROM asdf)
in a query like this other one.
SELECT b.foo
FROM (
SELECT DISTINCT stuff
FROM asdf ) a
JOIN bar b
ON b.stuff = a.stuff
You will also gain a lot of performance
Work around 'IN' clause limitation
Create a table function that will return your string results into a data-set that can be inserted into a CTE, temp table, or used directly in a join. This has been the most effective way for me to get around this limitation. Below is a link to Ole Michelsen's website who provides a simple but flexible solution.
Link: http://ole.michelsen.dk/blog/split-string-to-table-using-transact-sql.html
Sql Query IN clause limit 1 Record
You can add a ROW_NUMBER()
function based on the jobHistoryID
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[CustomerReadyDate].[JobHistoryDate] As [ConfirmLeadDate1],
[CustomerReadyDate].[JobColumnID]
FROM
[tblJob] Job
ON [Job].[JobID] = [StepJob].[JobID]
AND [Job].[SubmitTimestamp] > '2019-01-01'
LEFT JOIN (
SELECT
[JobHistory].[JobID],
[JobHistory].[JobHistoryDate],
[JobHistory].[JobColumnID],
[JobHistory].[JobHistoryID],
ROW_NUMBER() OVER(ORDER BY [JobHistoryID] DESC) rn
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE
[JobHistory].[jobColumnID] IN (251,252)
) AS [CustomerReadyDate]
ON [CustomerReadyDate].[JobID] = [Job].[JobID]
WHERE
[Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
AND [CustomerReadyDate].rn = 1
but i think you can optimize you query as the following:
SELECT * FROM (
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[JobHistory].[JobHistoryDate] As [ConfirmLeadDate1],
[JobHistory].[JobColumnID]
ROW_NUMBER() OVER(ORDER BY [JobHistoryID] DESC) rn
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE [JobHistory].[jobColumnID] IN (251,252)
AND [Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
) AS T1
WHERE T1.rn = 1
How to overcome resource limitation of IN operator in Microsoft SQL Server
You should transmit data to SQL Server like in related post
Sub UpdateTable()
Dim cnn As Object
Dim wbkOpen As Workbook
Dim objfl As Variant
Dim rngName As Range
Workbooks.Open "C:\your_path_here\Excel_to_SQL_Server.xls"
Set wbkOpen = ActiveWorkbook
Sheets("Sheet1").Select
Set rngName = Range(Range("A1"), Range("A1").End(xlToLeft).End(xlDown))
rngName.Name = "TempRange"
strFileName = wbkOpen.FullName
Set cnn = CreateObject("ADODB.Connection")
cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFileName & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes"";"
nSQL = "INSERT INTO [odbc;Driver={SQL Server};Server=Server_Name;Database=[Your_Database].[dbo].[TBL]]"
nJOIN = " SELECT * from [TempRange]"
cnn.Execute nSQL & nJOIN
MsgBox "Uploaded Successfully"
wbkOpen.Close
Set wbkOpen = Nothing
End Sub
and then you can do any you want - use operator IN or LEFT JOIN whith check for null on SQL server side.
You can use temporary table if you will not close connection - temp table exists only in session level.
This is way from VBA code.
Second way - you can use SSIS package to work with excel files. In package you will have same steps - data frlow to transmit data from excel to server and then run sql code to join data. Or you can use join block inside SSIS package.
Third way that you can implement if data in SQL server less than excel row count limit. You can import data from SQL into Excel sheet, and than use VLOOKUP() function to join tables and find related data.
Related Topics
Perform This Hours of Operation Query in Postgresql
How to Use SQL's Getdate() and Dateadd() in a Linq to SQL Expression
SQL - Difference Between Coalesce and Isnull
Create Table with Sequence.Nextval in Oracle
Insert Rows into Multiple Tables in a Single Query, Selecting from an Involved Table
How to Order by a Sum() in MySQL
Select Only Rows by Join Tables Max Value
Update If Exists Else Insert in SQL Server 2008
Sql:In Clause in Stored Procedure:How to Pass Values
If Exists Condition Not Working with Plsql
"In" Clause Limitation in SQL Server
Are There Any Way to Execute a Query Inside the String Value (Like Eval) in Postgresql
SQL Grouping by Month and Year
Get Next Sequence Value from Database Using Hibernate
How to Select Id with Max Date Group by Category in Postgresql