Passing table name as parameter to stored procedure with other additional parameters
-
Saturday, September 13, 2008 10:49 AMHi!I'm trying to write a stored procedure, that expects a table name as parameter, and also some other parameters that will be used as parameters in WHERE or in VALUES. However, I can't get this to work. If I only do aSELECT * FROM @table_name, it's fine, I can get that to work, however, I can't find a way to get a query likeSELECT * FROM @table_name WHERE PackageID = @packID to work.In the first case, I use the following code:ALTER PROCEDURE [dbo].[probaParamLek]@table_name varchar(50)ASBEGINSET NOCOUNT ON;SET @table_name = RTRIM(@table_name)DECLARE @cmd AS NVARCHAR(max)SET @cmd = N'SELECT * FROM ' + @table_nameEXEC sp_executesql @cmdENDThis above stored procedure works. When I try to achieve the other stored procedure as I mentioned above, it just simply doesn't work, and the error I get says nothing:ALTER PROCEDURE [dbo].[probaParamLek]@table_name varchar(50) ,@packID varchar(100)ASBEGINSET NOCOUNT ON;SET @table_name = RTRIM(@table_name)SET @packID = RTRIM(@packID)DECLARE @cmd AS NVARCHAR(max)SET @cmd = N'SELECT * FROM ' + @table_name + 'WHERE PackageID = ' + @packIDEXEC sp_executesql @cmdENDIs there a way to get the second stored procedure to work somehow? I'd also need this with UPDATE and INSERT commands. I need to get this to work, because I have a lot of the same table, but with different table names, and I don't want to create a stored procedure for each one of those tables, because if I can get this to work, it would be a lot easier. Also, with this string concatenation technique as I tried above, does the SQL server check the parameters, or am I risking SQL injection? If yes, then what can I do about it?Thanks in advance for the help!Zoli
All Replies
-
Saturday, September 13, 2008 11:47 AMIt looks like you need a space before the WHERE. The dynamic sql is running the table name and the WHERE clause together.
SET
@cmd = N'SELECT * FROM ' + @table_name + ' WHERE PackageID = ' + @packID -
Saturday, September 13, 2008 12:10 PMThank you for your answer, but unfortunately that didn't help either. (True, that was a mistake I made, but it still doesn't work this way.)Here is the error message I get when I try to execute it:Invalid column name 'something'where 'something' is the value of the @packID parameter I put in it when I try to execute it
-
Saturday, September 13, 2008 12:27 PM
It sounds like the packageid may need to be in quotes. Try this.
SET
@cmd = N'SELECT * FROM ' + @table_name + ' WHERE PackageID = ''' + @packID + '''' -
Saturday, September 13, 2008 12:57 PM
Just as a side note, but you should always make sure such procedures are not gonna be used as a SQL-injection attack vector. Object names are properly composed with a schema, so you should accept a schema parameter as well. Best practices recommend to pass in separate parts of the object name and use QUOTENAME to compose the name. varchar(50) is not an appropiate type for an object name, use the proper sysname type. Place a space in front of WHERE. And use again QUOTENAME with the single quote ' as the optional quote_character parameter to properly escape the @packID parameter, again to prevent a sql-injection attack vector:
ALTER PROCEDURE [dbo].[probaParamLek]
@schema sysname,@table_name sysname,@packID varchar(100)ASBEGINSET NOCOUNT ON;SET @table_name = RTRIM(@table_name)SET @packID = RTRIM(@packID)DECLARE @cmd AS NVARCHAR(max)SET @cmd = N'SELECT * FROM ' + QUOTENAME(@schema) + N'.' + QUOTENAME(@table_name) + N' WHERE PackageID = ' + QUOTENAME(@packID, '''')EXEC sp_executesql @cmdEND
Even better in your case would be to pass in the @packID as a parameter to the sp_executesql:
ALTER PROCEDURE [dbo].[probaParamLek]
@schema sysname,@table_name sysname,@packID varchar(100)ASBEGINSET NOCOUNT ON;SET @table_name = RTRIM(@table_name)SET @packID = RTRIM(@packID)DECLARE @cmd AS NVARCHAR(max)SET @cmd = N'SELECT * FROM ' + QUOTENAME(@schema) + N'.' + QUOTENAME(@table_name) + N' WHERE PackageID = @packID';EXEC sp_executesql @cmd, N'@packID varchar(100)', @packdID;END -
Saturday, September 13, 2008 2:47 PMThanks a lot for both replies!
The '''' was the problem, that's why it wasn't working, thanks again!Also, thank you for the SQL Injection prevention, that also helps me a lot and I'll do it that way!However I'm not sure about this schema parameter you mentioned. What input do I have to put there? -
Saturday, September 13, 2008 2:51 PM
Sz_Zoli wrote: Thanks a lot for both replies! However I'm not sure about this schema parameter you mentioned. What input do I have to put there?
If the table is in 'dbo' schema, then dbo. Otherwise you won't be able to pass in names of tables in other schemas.- Proposed As Answer by A H AN Thursday, July 23, 2009 8:48 AM
-
Saturday, September 13, 2008 3:09 PMAhh okay, thank you!
I understand now! -
Sunday, March 01, 2009 9:31 PM
im trying to create a stored prcedure that you pass
the table name end get the next autonumber from that atable ?
some help please where did i go wrong
example
CREATE PROCEDURE dbo.GetNextID
(@TableName Varchar(30),
@NextID integer OUTPUT)AS
SELECT @NextID = MAX(RecordID) + 1 FROM @TableName
RETURN @NextID -
Thursday, July 23, 2009 8:49 AM
try this
------------
CREATEPROC [dbo].[GetTablesDetails]
(
@tblName
nvarchar(100)
)
AS
BEGIN
DECLARE
@SQL nvarchar(100)
SET
@SQL = 'SELECT * FROM ' + @tblName
EXEC
(@SQL)
END
-
Thursday, July 23, 2009 12:22 PMThe risk of SQL injection has already been mentioned in this thread but I think it needs to be emphasized. Try this:EXEC dbo.GetTablesDetails 'dbo.Foo;DROP TABLE dbo.Foo;See http://www.sommarskog.se/dynamic_sql.html for a thorough discussion on dynamic SQL considerations.
--
Hope this helps."A H AN" wrote in message news:dc968c9c-3596-476 1-9395-213459e5d48e...try this
------------
CREATEPROC [dbo].[GetTablesDetails]
(
@tblName
nvarchar(100)
AS
BEGIN
DECLARE
@SQL nvarchar(100)
SET
@SQL = 'SELECT * FROM ' + @tblName
EXEC
(@SQL)
END
)
- Edited by Dan GuzmanMVP Friday, July 24, 2009 3:01 AM
-
Thursday, July 23, 2009 1:07 PMModeratorDan, you might want to redo the link.
-
Friday, July 24, 2009 3:04 AMThanks, Brian. I fixed the link to http://www.sommarskog.se/dynamic_sql.html
-
Friday, July 24, 2009 1:34 PMModeratorGlad i could be of service.
And while i have you attention... :)
Is there a link for comments RSS on your blog? -
Saturday, July 25, 2009 4:56 PMAnd while i have you attention... :)
Is there a link for comments RSS on your blog?Unfortunately, I don't currently have a comments RSS option available. I'm constrained by my blog Subtext version but will certainly include comments when available.
--
Hope this helps. -
Monday, July 27, 2009 12:55 PMModeratorThanx.
-
Thursday, August 02, 2012 7:22 PM
Thanks Dan excellent tutorial about risks of SQL Injection and how to avoid it... here http://www.sommarskog.se/dynamic_sql.html
I am currently working on a Windows desktop application but I want my stored procedures to be future proof in case in the future me or some other developer needs to build a web interface. For now I'm going to use sp_executesql and also format the sql string properly so that "Since the SQL String does not include any user input, there is no opening for injection" [as you mentioned aptly in your article].
This is what I"m thinking of doing:
1) I only need to get start and end dates of a report directly from a user - so instead of giving blank text fields for input, I"m using combo boxes for Day/month/year - that way the user IS FORCED to select an expected input format - he simply can't manipulate the SQL string.
2) I had a need to get table names as parameters, but now after reading your article I'm not using the table Name as a parameter directly and have instead already created static views with the table names I need ahead of time (there aren't too for my needs) and one of these static SQL views is called from my dynamic SQL stored procedure based on something a user clicks on - and not based on what he/she inputs in a text box. That way they can't enter weird SQL into my application.
- Edited by Gagan Coder Thursday, August 02, 2012 7:25 PM
- Edited by Gagan Coder Thursday, August 02, 2012 7:26 PM
- Edited by Gagan Coder Thursday, August 02, 2012 7:27 PM

