T-SQL stored procedure that accepts multiple Id values - sql-server

Is there a graceful way to handle passing a list of ids as a parameter to a stored procedure?
For instance, I want departments 1, 2, 5, 7, 20 returned by my stored procedure. In the past, I have passed in a comma delimited list of ids, like the below code, but feel really dirty doing it.
SQL Server 2005 is my only applicable limitation I think.
create procedure getDepartments
#DepartmentIds varchar(max)
as
declare #Sql varchar(max)
select #Sql = 'select [Name] from Department where DepartmentId in (' + #DepartmentIds + ')'
exec(#Sql)

Erland Sommarskog has maintained the authoritative answer to this question for the last 16 years: Arrays and Lists in SQL Server.
There are at least a dozen ways to pass an array or list to a query; each has their own unique pros and cons.
Table-Valued Parameters. SQL Server 2008 and higher only, and probably the closest to a universal "best" approach.
The Iterative Method. Pass a delimited string and loop through it.
Using the CLR. SQL Server 2005 and higher from .NET languages only.
XML. Very good for inserting many rows; may be overkill for SELECTs.
Table of Numbers. Higher performance/complexity than simple iterative method.
Fixed-length Elements. Fixed length improves speed over the delimited string
Function of Numbers. Variations of Table of Numbers and fixed-length where the number are generated in a function rather than taken from a table.
Recursive Common Table Expression (CTE). SQL Server 2005 and higher, still not too complex and higher performance than iterative method.
Dynamic SQL. Can be slow and has security implications.
Passing the List as Many Parameters. Tedious and error prone, but simple.
Really Slow Methods. Methods that uses charindex, patindex or LIKE.
I really can't recommend enough to read the article to learn about the tradeoffs among all these options.

Yeah, your current solution is prone to SQL injection attacks.
The best solution that I've found is to use a function that splits text into words (there are a few posted here, or you can use this one from my blog) and then join that to your table. Something like:
SELECT d.[Name]
FROM Department d
JOIN dbo.SplitWords(#DepartmentIds) w ON w.Value = d.DepartmentId

One method you might want to consider if you're going to be working with the values a lot is to write them to a temporary table first. Then you just join on it like normal.
This way, you're only parsing once.
It's easiest to use one of the 'Split' UDFs, but so many people have posted examples of those, I figured I'd go a different route ;)
This example will create a temporary table for you to join on (#tmpDept) and fill it with the department id's that you passed in. I'm assuming you're separating them with commas, but you can -- of course -- change it to whatever you want.
IF OBJECT_ID('tempdb..#tmpDept', 'U') IS NOT NULL
BEGIN
DROP TABLE #tmpDept
END
SET #DepartmentIDs=REPLACE(#DepartmentIDs,' ','')
CREATE TABLE #tmpDept (DeptID INT)
DECLARE #DeptID INT
IF IsNumeric(#DepartmentIDs)=1
BEGIN
SET #DeptID=#DepartmentIDs
INSERT INTO #tmpDept (DeptID) SELECT #DeptID
END
ELSE
BEGIN
WHILE CHARINDEX(',',#DepartmentIDs)>0
BEGIN
SET #DeptID=LEFT(#DepartmentIDs,CHARINDEX(',',#DepartmentIDs)-1)
SET #DepartmentIDs=RIGHT(#DepartmentIDs,LEN(#DepartmentIDs)-CHARINDEX(',',#DepartmentIDs))
INSERT INTO #tmpDept (DeptID) SELECT #DeptID
END
END
This will allow you to pass in one department id, multiple id's with commas in between them, or even multiple id's with commas and spaces between them.
So if you did something like:
SELECT Dept.Name
FROM Departments
JOIN #tmpDept ON Departments.DepartmentID=#tmpDept.DeptID
ORDER BY Dept.Name
You would see the names of all of the department IDs that you passed in...
Again, this can be simplified by using a function to populate the temporary table... I mainly did it without one just to kill some boredom :-P
-- Kevin Fairchild

You could use XML.
E.g.
declare #xmlstring as varchar(100)
set #xmlstring = '<args><arg value="42" /><arg2>-1</arg2></args>'
declare #docid int
exec sp_xml_preparedocument #docid output, #xmlstring
select [id],parentid,nodetype,localname,[text]
from openxml(#docid, '/args', 1)
The command sp_xml_preparedocument is built in.
This would produce the output:
id parentid nodetype localname text
0 NULL 1 args NULL
2 0 1 arg NULL
3 2 2 value NULL
5 3 3 #text 42
4 0 1 arg2 NULL
6 4 3 #text -1
which has all (more?) of what you you need.

A superfast XML Method, if you want to use a stored procedure and pass the comma separated list of Department IDs :
Declare #XMLList xml
SET #XMLList=cast('<i>'+replace(#DepartmentIDs,',','</i><i>')+'</i>' as xml)
SELECT x.i.value('.','varchar(5)') from #XMLList.nodes('i') x(i))
All credit goes to Guru Brad Schulz's Blog

Related

Is there any way to find comma separated string in where clause in SQL [duplicate]

Is there a graceful way to handle passing a list of ids as a parameter to a stored procedure?
For instance, I want departments 1, 2, 5, 7, 20 returned by my stored procedure. In the past, I have passed in a comma delimited list of ids, like the below code, but feel really dirty doing it.
SQL Server 2005 is my only applicable limitation I think.
create procedure getDepartments
#DepartmentIds varchar(max)
as
declare #Sql varchar(max)
select #Sql = 'select [Name] from Department where DepartmentId in (' + #DepartmentIds + ')'
exec(#Sql)
Erland Sommarskog has maintained the authoritative answer to this question for the last 16 years: Arrays and Lists in SQL Server.
There are at least a dozen ways to pass an array or list to a query; each has their own unique pros and cons.
Table-Valued Parameters. SQL Server 2008 and higher only, and probably the closest to a universal "best" approach.
The Iterative Method. Pass a delimited string and loop through it.
Using the CLR. SQL Server 2005 and higher from .NET languages only.
XML. Very good for inserting many rows; may be overkill for SELECTs.
Table of Numbers. Higher performance/complexity than simple iterative method.
Fixed-length Elements. Fixed length improves speed over the delimited string
Function of Numbers. Variations of Table of Numbers and fixed-length where the number are generated in a function rather than taken from a table.
Recursive Common Table Expression (CTE). SQL Server 2005 and higher, still not too complex and higher performance than iterative method.
Dynamic SQL. Can be slow and has security implications.
Passing the List as Many Parameters. Tedious and error prone, but simple.
Really Slow Methods. Methods that uses charindex, patindex or LIKE.
I really can't recommend enough to read the article to learn about the tradeoffs among all these options.
Yeah, your current solution is prone to SQL injection attacks.
The best solution that I've found is to use a function that splits text into words (there are a few posted here, or you can use this one from my blog) and then join that to your table. Something like:
SELECT d.[Name]
FROM Department d
JOIN dbo.SplitWords(#DepartmentIds) w ON w.Value = d.DepartmentId
One method you might want to consider if you're going to be working with the values a lot is to write them to a temporary table first. Then you just join on it like normal.
This way, you're only parsing once.
It's easiest to use one of the 'Split' UDFs, but so many people have posted examples of those, I figured I'd go a different route ;)
This example will create a temporary table for you to join on (#tmpDept) and fill it with the department id's that you passed in. I'm assuming you're separating them with commas, but you can -- of course -- change it to whatever you want.
IF OBJECT_ID('tempdb..#tmpDept', 'U') IS NOT NULL
BEGIN
DROP TABLE #tmpDept
END
SET #DepartmentIDs=REPLACE(#DepartmentIDs,' ','')
CREATE TABLE #tmpDept (DeptID INT)
DECLARE #DeptID INT
IF IsNumeric(#DepartmentIDs)=1
BEGIN
SET #DeptID=#DepartmentIDs
INSERT INTO #tmpDept (DeptID) SELECT #DeptID
END
ELSE
BEGIN
WHILE CHARINDEX(',',#DepartmentIDs)>0
BEGIN
SET #DeptID=LEFT(#DepartmentIDs,CHARINDEX(',',#DepartmentIDs)-1)
SET #DepartmentIDs=RIGHT(#DepartmentIDs,LEN(#DepartmentIDs)-CHARINDEX(',',#DepartmentIDs))
INSERT INTO #tmpDept (DeptID) SELECT #DeptID
END
END
This will allow you to pass in one department id, multiple id's with commas in between them, or even multiple id's with commas and spaces between them.
So if you did something like:
SELECT Dept.Name
FROM Departments
JOIN #tmpDept ON Departments.DepartmentID=#tmpDept.DeptID
ORDER BY Dept.Name
You would see the names of all of the department IDs that you passed in...
Again, this can be simplified by using a function to populate the temporary table... I mainly did it without one just to kill some boredom :-P
-- Kevin Fairchild
You could use XML.
E.g.
declare #xmlstring as varchar(100)
set #xmlstring = '<args><arg value="42" /><arg2>-1</arg2></args>'
declare #docid int
exec sp_xml_preparedocument #docid output, #xmlstring
select [id],parentid,nodetype,localname,[text]
from openxml(#docid, '/args', 1)
The command sp_xml_preparedocument is built in.
This would produce the output:
id parentid nodetype localname text
0 NULL 1 args NULL
2 0 1 arg NULL
3 2 2 value NULL
5 3 3 #text 42
4 0 1 arg2 NULL
6 4 3 #text -1
which has all (more?) of what you you need.
A superfast XML Method, if you want to use a stored procedure and pass the comma separated list of Department IDs :
Declare #XMLList xml
SET #XMLList=cast('<i>'+replace(#DepartmentIDs,',','</i><i>')+'</i>' as xml)
SELECT x.i.value('.','varchar(5)') from #XMLList.nodes('i') x(i))
All credit goes to Guru Brad Schulz's Blog

Insert multiple values into multiple rows using one parameter in T-SQL

I am building an application using Microsoft Access as a front-end and SQL Server as the back end.
I have a Stored Procedure that inserts customer information. One of the pieces of information that will be inserted for each customer are their Credit Card numbers. The number of credit cards for each customer could be anywhere from 1-50.
I am planning on using a Dynamic array in VBA to add the credit card numbers. The trouble I am having is I am not quite sure how to pass the values to the stored procedure.
My first thought was to create a ton of parameters (CC Number 1, CC Number 2, CC Number 3,etc) but obviously this isn't the correct way to do it.
After the credit card numbers have been added to the Dynamic Array, I can ReDim it to get the count of how many credit card numbers I will need to insert.
What would be the best way to pass lets say, 14 credit card values to one parameter and insert each value as a new row?
Unfortunately, AFAIK, VBA doesn't support table valued parameters (ADO.NET does, but not the vanilla VB6 implementation that we have to use in Access).
You could send a stream of function calls to the server by looping through a recordset or something, but that's going to be painfully slow. If you don't mind repeating yourself, though, you could send one big command that contains a bunch of EXEC statements chained one after the other (if you're using DAO, be sure to specify SET NOCOUNT ON at the start of the query).
If you're looking for a pure-SQL solution, here's the strategy I take for these sorts of problems:
Concatenate the array of values into a string with some sort of separator (e.g. "," or "|").
Pass the string to a function or query that converts it to a table of values.
INSERT or MERGE the table of values into the final target table.
Here's an example of how you can do it:
SET NOCOUNT ON
DECLARE #x XML;
DECLARE #CreditCards AS TABLE (CreditCardNumber VARCHAR(16));
DECLARE #FinalTable AS TABLE (CreditCardNumber VARCHAR(16));
DECLARE #CreditCardList AS VARCHAR(8000);
DECLARE #Divider AS Varchar(10);
SET #Divider=',';
SET #CreditCardList='1234567890123456,1111111111111111,2222222222222222,123456789012345';
IF NOT #CreditCardList IS NULL
BEGIN
SELECT #x = CAST('<A>'+ REPLACE(#CreditCardList,#Divider,'</A><A>')+ '</A>' AS XML);
INSERT INTO
#CreditCards
SELECT
t.value('.', 'varchar(16)') AS inVal
FROM
#x.nodes('/A') AS x(t) ;
END
INSERT INTO
#FinalTable
SELECT
CreditCardNumber
FROM
#CreditCards
SELECT * FROM #FinaLTable
XML isn't the fastest way to do the conversion, but it has the benefit of being relatively straightforward. Jeff Moden provides several pretty inspired approaches to the problem in his blog post Tally OH! An Improved SQL 8K “CSV Splitter” Function.
Hope that helps!
Use XML to pass all customer information in one document. This way you can pass any number of parameters and query it on server as a table.

Stored procedure that accepts multiple primary key and get the values [duplicate]

Is there a graceful way to handle passing a list of ids as a parameter to a stored procedure?
For instance, I want departments 1, 2, 5, 7, 20 returned by my stored procedure. In the past, I have passed in a comma delimited list of ids, like the below code, but feel really dirty doing it.
SQL Server 2005 is my only applicable limitation I think.
create procedure getDepartments
#DepartmentIds varchar(max)
as
declare #Sql varchar(max)
select #Sql = 'select [Name] from Department where DepartmentId in (' + #DepartmentIds + ')'
exec(#Sql)
Erland Sommarskog has maintained the authoritative answer to this question for the last 16 years: Arrays and Lists in SQL Server.
There are at least a dozen ways to pass an array or list to a query; each has their own unique pros and cons.
Table-Valued Parameters. SQL Server 2008 and higher only, and probably the closest to a universal "best" approach.
The Iterative Method. Pass a delimited string and loop through it.
Using the CLR. SQL Server 2005 and higher from .NET languages only.
XML. Very good for inserting many rows; may be overkill for SELECTs.
Table of Numbers. Higher performance/complexity than simple iterative method.
Fixed-length Elements. Fixed length improves speed over the delimited string
Function of Numbers. Variations of Table of Numbers and fixed-length where the number are generated in a function rather than taken from a table.
Recursive Common Table Expression (CTE). SQL Server 2005 and higher, still not too complex and higher performance than iterative method.
Dynamic SQL. Can be slow and has security implications.
Passing the List as Many Parameters. Tedious and error prone, but simple.
Really Slow Methods. Methods that uses charindex, patindex or LIKE.
I really can't recommend enough to read the article to learn about the tradeoffs among all these options.
Yeah, your current solution is prone to SQL injection attacks.
The best solution that I've found is to use a function that splits text into words (there are a few posted here, or you can use this one from my blog) and then join that to your table. Something like:
SELECT d.[Name]
FROM Department d
JOIN dbo.SplitWords(#DepartmentIds) w ON w.Value = d.DepartmentId
One method you might want to consider if you're going to be working with the values a lot is to write them to a temporary table first. Then you just join on it like normal.
This way, you're only parsing once.
It's easiest to use one of the 'Split' UDFs, but so many people have posted examples of those, I figured I'd go a different route ;)
This example will create a temporary table for you to join on (#tmpDept) and fill it with the department id's that you passed in. I'm assuming you're separating them with commas, but you can -- of course -- change it to whatever you want.
IF OBJECT_ID('tempdb..#tmpDept', 'U') IS NOT NULL
BEGIN
DROP TABLE #tmpDept
END
SET #DepartmentIDs=REPLACE(#DepartmentIDs,' ','')
CREATE TABLE #tmpDept (DeptID INT)
DECLARE #DeptID INT
IF IsNumeric(#DepartmentIDs)=1
BEGIN
SET #DeptID=#DepartmentIDs
INSERT INTO #tmpDept (DeptID) SELECT #DeptID
END
ELSE
BEGIN
WHILE CHARINDEX(',',#DepartmentIDs)>0
BEGIN
SET #DeptID=LEFT(#DepartmentIDs,CHARINDEX(',',#DepartmentIDs)-1)
SET #DepartmentIDs=RIGHT(#DepartmentIDs,LEN(#DepartmentIDs)-CHARINDEX(',',#DepartmentIDs))
INSERT INTO #tmpDept (DeptID) SELECT #DeptID
END
END
This will allow you to pass in one department id, multiple id's with commas in between them, or even multiple id's with commas and spaces between them.
So if you did something like:
SELECT Dept.Name
FROM Departments
JOIN #tmpDept ON Departments.DepartmentID=#tmpDept.DeptID
ORDER BY Dept.Name
You would see the names of all of the department IDs that you passed in...
Again, this can be simplified by using a function to populate the temporary table... I mainly did it without one just to kill some boredom :-P
-- Kevin Fairchild
You could use XML.
E.g.
declare #xmlstring as varchar(100)
set #xmlstring = '<args><arg value="42" /><arg2>-1</arg2></args>'
declare #docid int
exec sp_xml_preparedocument #docid output, #xmlstring
select [id],parentid,nodetype,localname,[text]
from openxml(#docid, '/args', 1)
The command sp_xml_preparedocument is built in.
This would produce the output:
id parentid nodetype localname text
0 NULL 1 args NULL
2 0 1 arg NULL
3 2 2 value NULL
5 3 3 #text 42
4 0 1 arg2 NULL
6 4 3 #text -1
which has all (more?) of what you you need.
A superfast XML Method, if you want to use a stored procedure and pass the comma separated list of Department IDs :
Declare #XMLList xml
SET #XMLList=cast('<i>'+replace(#DepartmentIDs,',','</i><i>')+'</i>' as xml)
SELECT x.i.value('.','varchar(5)') from #XMLList.nodes('i') x(i))
All credit goes to Guru Brad Schulz's Blog

how to use 'in' Operator in ,SQL Queries Stored Procedures,passing Multiple Values in a single parameter [duplicate]

Is there a graceful way to handle passing a list of ids as a parameter to a stored procedure?
For instance, I want departments 1, 2, 5, 7, 20 returned by my stored procedure. In the past, I have passed in a comma delimited list of ids, like the below code, but feel really dirty doing it.
SQL Server 2005 is my only applicable limitation I think.
create procedure getDepartments
#DepartmentIds varchar(max)
as
declare #Sql varchar(max)
select #Sql = 'select [Name] from Department where DepartmentId in (' + #DepartmentIds + ')'
exec(#Sql)
Erland Sommarskog has maintained the authoritative answer to this question for the last 16 years: Arrays and Lists in SQL Server.
There are at least a dozen ways to pass an array or list to a query; each has their own unique pros and cons.
Table-Valued Parameters. SQL Server 2008 and higher only, and probably the closest to a universal "best" approach.
The Iterative Method. Pass a delimited string and loop through it.
Using the CLR. SQL Server 2005 and higher from .NET languages only.
XML. Very good for inserting many rows; may be overkill for SELECTs.
Table of Numbers. Higher performance/complexity than simple iterative method.
Fixed-length Elements. Fixed length improves speed over the delimited string
Function of Numbers. Variations of Table of Numbers and fixed-length where the number are generated in a function rather than taken from a table.
Recursive Common Table Expression (CTE). SQL Server 2005 and higher, still not too complex and higher performance than iterative method.
Dynamic SQL. Can be slow and has security implications.
Passing the List as Many Parameters. Tedious and error prone, but simple.
Really Slow Methods. Methods that uses charindex, patindex or LIKE.
I really can't recommend enough to read the article to learn about the tradeoffs among all these options.
Yeah, your current solution is prone to SQL injection attacks.
The best solution that I've found is to use a function that splits text into words (there are a few posted here, or you can use this one from my blog) and then join that to your table. Something like:
SELECT d.[Name]
FROM Department d
JOIN dbo.SplitWords(#DepartmentIds) w ON w.Value = d.DepartmentId
One method you might want to consider if you're going to be working with the values a lot is to write them to a temporary table first. Then you just join on it like normal.
This way, you're only parsing once.
It's easiest to use one of the 'Split' UDFs, but so many people have posted examples of those, I figured I'd go a different route ;)
This example will create a temporary table for you to join on (#tmpDept) and fill it with the department id's that you passed in. I'm assuming you're separating them with commas, but you can -- of course -- change it to whatever you want.
IF OBJECT_ID('tempdb..#tmpDept', 'U') IS NOT NULL
BEGIN
DROP TABLE #tmpDept
END
SET #DepartmentIDs=REPLACE(#DepartmentIDs,' ','')
CREATE TABLE #tmpDept (DeptID INT)
DECLARE #DeptID INT
IF IsNumeric(#DepartmentIDs)=1
BEGIN
SET #DeptID=#DepartmentIDs
INSERT INTO #tmpDept (DeptID) SELECT #DeptID
END
ELSE
BEGIN
WHILE CHARINDEX(',',#DepartmentIDs)>0
BEGIN
SET #DeptID=LEFT(#DepartmentIDs,CHARINDEX(',',#DepartmentIDs)-1)
SET #DepartmentIDs=RIGHT(#DepartmentIDs,LEN(#DepartmentIDs)-CHARINDEX(',',#DepartmentIDs))
INSERT INTO #tmpDept (DeptID) SELECT #DeptID
END
END
This will allow you to pass in one department id, multiple id's with commas in between them, or even multiple id's with commas and spaces between them.
So if you did something like:
SELECT Dept.Name
FROM Departments
JOIN #tmpDept ON Departments.DepartmentID=#tmpDept.DeptID
ORDER BY Dept.Name
You would see the names of all of the department IDs that you passed in...
Again, this can be simplified by using a function to populate the temporary table... I mainly did it without one just to kill some boredom :-P
-- Kevin Fairchild
You could use XML.
E.g.
declare #xmlstring as varchar(100)
set #xmlstring = '<args><arg value="42" /><arg2>-1</arg2></args>'
declare #docid int
exec sp_xml_preparedocument #docid output, #xmlstring
select [id],parentid,nodetype,localname,[text]
from openxml(#docid, '/args', 1)
The command sp_xml_preparedocument is built in.
This would produce the output:
id parentid nodetype localname text
0 NULL 1 args NULL
2 0 1 arg NULL
3 2 2 value NULL
5 3 3 #text 42
4 0 1 arg2 NULL
6 4 3 #text -1
which has all (more?) of what you you need.
A superfast XML Method, if you want to use a stored procedure and pass the comma separated list of Department IDs :
Declare #XMLList xml
SET #XMLList=cast('<i>'+replace(#DepartmentIDs,',','</i><i>')+'</i>' as xml)
SELECT x.i.value('.','varchar(5)') from #XMLList.nodes('i') x(i))
All credit goes to Guru Brad Schulz's Blog

Searching on a table whose name is defined in a variable

simple problem, but perhaps no simple solution, at least I can't think of one of the top of my head but then I'm not the best at finding the best solutions.
I have a stored proc, this stored proc does (in a basic form) a select on a table, envision this:
SELECT * FROM myTable
okay, simple enough, except the table name it needs to search on isn't known, so we ended up with something pretty similiar to this:
-- Just to give some context to the variables I'll be using
DECLARE #metaInfoID AS INT
SET #metaInfoID = 1
DECLARE #metaInfoTable AS VARCHAR(200)
SELECT #metaInfoTable = MetaInfoTableName FROM MetaInfos WHERE MetaInfoID = #MetaInfoID
DECLARE #sql AS VARCHAR(200)
SET #sql = 'SELECT * FROM ' + #metaInfoTable
EXEC #sql
So, I, recognize this is ultimately bad, and can see immediately where I can perform a sql injection attack. So, the question is, is there a way to achieve the same results without the construction of the dynamic sql? or am I going to have to be super, super careful in my client code?
You have to use dynamic sql if you don't know the table name up front. But yes, you should validate the value before attempting to use it in an SQL statement.
e.g.
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=#metaInfoTable)
BEGIN
-- Execute the SELECT * FROM #metaInfoTable dynamic sql
END
This will make sure a table with that name exists. There is an overhead to doing this obviously as you're querying INFORMATION_SCHEMA. You could instead validate the #metaInfoTable contains only certain characters:
-- only run dynamic sql if table name value contains 0-9,a-z,A-Z, underscores or spaces (enclose table name in square brackets, in case it does contain spaces)
IF NOT #metaInfoTable LIKE '%^[0-9a-zA-Z_ ]%'
BEGIN
-- Execute the SELECT * FROM #metaInfoTable dynamic sql
END
Given the constraints described, I'd suggest 2 ways, with slight variations in performance an architecture.
Choose At the Client & Re-Architect
I'd suggest that you should consider a small re-architecture as much as possible to force the caller/client to decide which table to get its data from. It's a code smell to hold table names in another table.
I am taking an assumption here that #MetaInfoID is being passed from a webapp, data access block, etc. That's where the logic of which table to perform the SELECT on should be housed. I'd say that the client should know which stored procedure (GetCustomers or GetProducts) to call based on that #MetaInfoID. Create new method in your DAL like GetCustomersMetaInfo() and GetProductsMetaInfo() and GetInvoicesMetaInfo() which call into their appropriate sprocs (with no dynamic SQL needed, and no maintenance of a meta table in the DB).
Perhaps try to re-architect the system a little bit.
In SQL Server
If you absolutely have to do this lookup in the DB, and depending on the number of tables that you have, you could perform a handful of IF statements (as many as needed) like:
IF #MetaInfoID = 1
SELECT * FROM Customers
IF #MetaInfoID =2
SELECT * FROM Products
-- etc
That would probably become to be a nightmare to maintain.
Perhaps you could write a stored procedure for each MetaInfo. In this way, you gain the advantage of pre-compilation, and no SQL injection can occur here. (imagine if someone sabotaged the MetaInfoTableName column)
IF #MetaInfoID = 1
EXEC GetAllCustomers
IF #MetaInfoID = 2
EXEC GetAllProducts

Resources