1

Let's say in my Excel sheet, I have the following "table":

ZipCodes |
---------+
  4059   |
  5806   |
  4529   |

I need to get the data from a SQL Server view WHERE column ZipCodes has one of the values in my Excel table.

I want the user to be able to add as many ZipCodes as he wants, while not adjusting the query manually.

I've looked that this question but I cannot get it working.

I'm stuck with passing a list of values to the sql query. It's working if I am passing a single ZipCode.

Sth. like this would help me:

WHERE  ZipCode IN (SELECT * FROM  [sheet2$a1:a2])

but that's breaking the query.

9
  • Where is this Excel document? Is it a static file, or is it going to be one that the user "supplies" to the data engine? Commented Apr 10, 2018 at 8:14
  • but I cannot get it working Show us what did you try and which point you stuck at. Commented Apr 10, 2018 at 8:14
  • @Larnu the file will be setup by admins and will be supplied to endusers. They should review the data and they may add more zipcodes in the future. Commented Apr 10, 2018 at 8:17
  • "supplied to endusers"? So, it'll be located on their PC, in their email? Does your SQL Server have access to their local files (I assume not, and it should not). if they're updating the file, are they then resaving it locally? You can use things like OPENROWSET, but the file needs to be in a network location that the SQL Server's Service account has permission to access. Commented Apr 10, 2018 at 8:19
  • @Larnu I will create a new readonly user for only a single view. The server is accessible to anyone. Commented Apr 10, 2018 at 8:20

1 Answer 1

2

One solution here would be to use OPENROWSET. After discussion, it does appear that the location of the Excel file can and will change; this is fine but means we need to build a dynamic SQL solution, as OPENROWSET requires literal strings for it's parameters (no variables).

Firstly, I don't know what what version of the ACE Drivers you have installed. As a result in my code I am using the drivers I have installed; which are the 2010 drivers (version 12). If that's not the version you're using, you'll need to change the value that I comment.

Normally, an OPENROWSET query might look like this:

SELECT *
FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0', --This declares the Driver. You may need to change this
                'Excel 8.0;HDR=YES;;Database=\\YourFileServer\yourShare\YourFile.xlsx',
                'SELECT *
                FROM [Sheet1$A1:G];');

This'll return all rows from columns A through to G, starting at Row 2. Row 1 will be assumed to contain the Header (HDR=YES); if you don't have headers use HDR=NO.

The problem here is that we can't pass a a variable here. Thus we need to do something more dynamic. This gets you something along the lines of:

DECLARE @File nvarchar(500); --This would be your parameter
SET @File = N'\\YourFileServer\yourShare\YourFile.xlsx';

DECLARE @SQL nvarchar(MAX);
SET @SQL = N'SELECT *' + NCHAR(10) +
           N'FROM OPENROWSET(''Microsoft.ACE.OLEDB.12.0'',' + NCHAR(10) +
           N'                ' + QUOTENAME(N'Excel 8.0;HDR=YES;Database=' + @File,N'''') + N','  + NCHAR(10) +
           N'                ''SELECT *'  + NCHAR(10) +
           N'                 FROM [Sheet1$A1:G];'');';
PRINT @SQL;
EXEC sp_executesql @SQL;

Now, finally, you want to use this data against your table/view. This, therefore, might finally look something like this (assuming your view is called Customer_vw, the data in the excel file in in column A, and the column in both datasets is called ZipCode):

DECLARE @File nvarchar(500); --This would be your parameter
SET @File = N'\\YourFileServer\yourShare\YourFile.xlsx';

DECLARE @SQL nvarchar(MAX);
SET @SQL = N'WITH ExcelZips AS (' + NCHAR(10) +
           N'    SELECT ZipCode' + NCHAR(10) +
           N'    FROM OPENROWSET(''Microsoft.ACE.OLEDB.12.0'',' + NCHAR(10) +
           N'                    ' + QUOTENAME(N'Excel 8.0;HDR=YES;Database=' + @File,N'''') + N','  + NCHAR(10) +
           N'                    ''SELECT *'  + NCHAR(10) +
           N'                     FROM [Sheet1$A1:A];''))' + NCHAR(10) +
           N'SELECT [YourColumns]' + NCHAR(10) +
           N'FROM Customer_vw C' + NCHAR(10) +
           N'     JOIN ExcelZips EZ ON C.ZipCode = EZ.ZipCode --Note that EZ.ZipCode will not show in intellisense' + NCHAR(10) +
           N'WHERE ...;'; --You'll need to complete the WHERE here, and add any ORDER BY etc.
PRINT @SQL;
EXEC sp_executesql @SQL;

Note that I have PRINT statements in the queries. These are your friends. I (personally) suggest that you comment out the EXEC statements first, and just use the PRINT statements. Check that the output from the PRINT looks correct. If it does then run it, and if you get an error trouble shoot the output from the PRINT, rather than the dynamic SQL. Once you've fixed the non-dynamic SQL, propagate the changes to the dynamic SQL.

Hopefully that explains everything. If you have any questions, please do ask.

Sign up to request clarification or add additional context in comments.

1 Comment

thanks alot ! Will try your solution and give feedback !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.