views:

52

answers:

3

I have a simple query that updates a variable column. This query is later string.Formatted and passed to SqlCommand (c#) (TableId is a column in SomeTable):

"UPDATE SomeTable set {0}=@Value where TableId=@TableId"

I need to convert this query to a stored procedure. Is it possible at all?

+4  A: 

I'm making a few assumptions about what you're doing, but evaluate this code.

CREATE PROCEDURE UpdateTableValue
    (
     @tableId INT
    ,@columnName sql_variant
    ,@value VARCHAR(10)
    )
AS 
    BEGIN

        DECLARE @sql NVARCHAR(MAX)
        SET @sql = N'UPDATE SomeTable '
                   + N'SET ' + QUOTENAME(@columnName) + N' = = @value '
                   + N'WHERE TableId = @tableId'

     EXEC sp_executesql @sql
             , N'@value sql_variant, @tableId int'
             , @value, @tableId;

    END
Brad
+6  A: 

It can only be done through dynamic SQL in the stored procedure (as Brad has alreayd answered, but of course you'd use QUOTENAME(@columnName) to properly protect against SQL injection, and use a sysname parameter type). If you go down that path, I recommend you read up first The Curse and Blessings of Dynamic SQL.

Updated:

I had to post code, since Brad's code has just too many mistakes.

create procedure myCustomUpdate
   @columnName sysname,
   @value sql_variant,
   @id int
AS
declare @sql NVARCHAR(max);
set @sql = N'UPDATE SomeTable SET ' + QUOTENAME(@columnName) 
    + N' = @value WHERE TableId = @id';
exec sp_executesql @sql, N'@value sql_variant, @id int', @value, @id;
Remus Rusanu
+1 - They really should just code into StackOverflow that whenever "Dynamic SQL" is entered it automatically hyperlinks to that article...
JNK
Thanks for the improvements Remuss. I guess it's no wonder you have 56k rep and I have yet to reach 2k :) I agree you should protect against injection, but would you *really* use quotes around the column name?
Brad
If any of these data are not actually hardcoded, then you should... I have to say, I am curious as to the point of this. What purpose is there in using a stored procedure that basically runs a query that is entirely defined by its parameters? Why not just skip the SP entirely and write the whole query in code?
jamietre
@Brad: yes, I would always use QUOTENAME, it just a basic good habit. Is not only SQL injection protection, but is also that the table may have a column with a space in its name like `Total Amount`. The other issues you already corrected.
Remus Rusanu
thanks, you guys rock!
kateroh
@Remus: +1 for jamietre. Do you know what would be the advantage of having this query in such a stored procedure vs having it in code? They both come from dynamically constructed strings...
kateroh
@Kateroch: the one reason whyan SP may make more sense is if UPDATE permission on the table is not granted to the application, but EXECUTE on the SP is. This separation is common in enterprise environments, it gives the DBA/admins control over *how* updates are performed, and *what* updates are allowed by modifying the procedure(s).
Remus Rusanu
I get an error when I try to execute this stored procedure: Msg 257, Level 16, State 3, Line 1Implicit conversion from data type sql_variant to int is not allowed. Use the CONVERT function to run this query.
kateroh
+1  A: 

I think there is a better solution in the article that Remus mentioned: The Curse and Blessings of Dynamic SQL . I ended up using CASE switches to optimize performance (dynamic SQL is not being cached) like in the article:

UPDATE tbl
SET    col1 = CASE @colname WHEN 'col1' THEN @value ELSE col1 END,
       col2 = CASE @colname WHEN 'col2' THEN @value ELSE col2 END,
kateroh