Dynamic IN without Dynamic T-Sql for Sql Server

Here is stripped down T-Sql code that illustrates a “no dynamic sql” approach to the common requirement for SQL Server stored procedures to accept comma delimited ID values while maintaining strong types. SQL Server @TableVariables are more efficient than regular temp tables and enhance the performance and scalability of this technique. However @TableVariables are _NOT_ implemented as in-memory datastructures and _DO_ write to tempdb. For more information on this data type see the Microsoft Table Variable FAQ [microsoft.com].

This example assumes an Employee table with a varchar(50) EmployeeID field. @IDList is the dynamically created (by the calling app) comma delimited list of IDs to return. That comma delimited @IDlist is parsed and inserted as separate records into the @TableVar so they can be used for the IN clause without dynamic sql.

Among other things, avoiding dynamic sql allows an administrator to grant privileges for users to run the procedure even SELECT privileges have been removed.

CREATE PROCEDURE [dbo].[SelectEmployeesByID] 
@IDList varchar(2000) 
AS 
set arithignore on 
set arithabort off 
set ansi_warnings off 
set nocount on 
declare @IDListPosition int 
declare @ArrValue varchar(2000) 
--must declare correct data type for IDs 
declare @TableVar table ( EmployeeID varchar(50) NOT NULL ) 
set @IDList = COALESCE(@IDList ,'') 
IF @IDList <> '' 
BEGIN 
--add comma to end of list so user doesn't have to 
set @IDList = @IDList + ',' 
-- Loop through the comma delimited string list 
while patindex('%,%' , @IDList ) <> 0 
begin 
select @IDListPosition = patindex('%,%' , @IDList) 
select @ArrValue = left(@IDList, @IDListPosition - 1) 
-- Insert parsed ID into TableVar for "where in select"
INSERT INTO @TableVar (EmployeeID) VALUES (@ArrValue) 
-- Remove processed string 
select @IDList = stuff(@IDList, 1, @IDListPosition, '') 
END 
END
SELECT 
*
FROM 
[Employee] 
WHERE 
( 
[EmployeeID] IN (SELECT EmployeeID FROM @TableVar) 
) 
ORDER BY EmployeeID ASC;

or, for a possible performance boost, try adjusting the SELECT clause to a logically equivalent variation by dropping the IN operation in favor of doing an inner join on @tablevar like so :

SELECT 
* 
FROM 
[Employee] INNER JOIN @TableVar 
ON [Employee].EmployeeID = @TableVar.EmployeeID
ORDER BY [Employee].EmployeeID ASC;

to run the proc (for either formulation):

exec SelectEmployeesByID 'a48345,a34598,r9834,l234'