2

I have a table dbo.t_products and I want to know the last record updated. For that I have an attribute last_changed which stores for each record the timestamp of the last update.

Finally I want to save that result in a variable called @y.

DECLARE @y DATETIME
DECLARE @p_table VARCHAR(100)

SET @p_table = 'dbo.t_products'

EXECUTE sp_executesql N'SET @y = SELECT MAX(last_changed) FROM @p_table'
                        ,N'@p_table VARCHAR, @y DATETIME OUTPUT'
                        ,@p_table
                        ,@y OUTPUT
SELECT @y

The system returns the following message:

Msg 156, Level 15, State 1, Line 25
Incorrect syntax near the keyword 'SELECT'.

Any ideas?

6
  • 3
    The first step for debugging dynamic SQL is to print the SQL you are trying to execute - then the reason for the error will normally become obvious. Commented Mar 11, 2020 at 20:17
  • I am not sure I clearly followed the statement EXECUTE sp_executesql .... but one obvious thing that I see is, @p_table is repeated. Could you just mention plain statement (like what would be resultant dynamic statement) Commented Mar 11, 2020 at 20:18
  • 6
    This will never work like this. You can't parameterize object names. Commented Mar 11, 2020 at 20:22
  • Try it with your SELECT statement in parentheses. Gets you past "Incorrect syntax near the keyword 'SELECT'." Commented Mar 11, 2020 at 20:22
  • 1
    If you found the answer provide by @DaleK helpful, you should really ACCEPT it meta.stackexchange.com/questions/5234/… Commented Mar 11, 2020 at 21:25

1 Answer 1

4

The whole point of using dynamic SQL in your case (I assume) is to allow the use of a dynamic table name. In which case you have to insert the table name into the dynamic SQL string - you can't pass it in as a parameter, thats the problem you are trying in the first place.

Also you don't need a SET followed by a SELECT just use SELECT directly to set the variable.

Finally you definitely want to use the QUOTENAME function to escape your table name and avoid an SQL injection attack - this requires you split the table name and schema name.

DECLARE @y DATETIME;
DECLARE @p_schema VARCHAR(100);
DECLARE @p_table VARCHAR(100);
DECLARE @SQL NVARCHAR(max);

SET @p_schema = 'dbo';
SET @p_table = 't_products';
-- Add the table name to the dynamic SQL 
SET @SQL = 'SELECT @y = MAX(last_changed) FROM ' + QUOTENAME(@p_schema) + '.' + QUOTENAME(@p_table);

EXECUTE sp_executesql @SQL, N'@y DATETIME OUTPUT', @y OUTPUT;

-- PRINT(@SQL); --- Debugging

SELECT @y;
Sign up to request clarification or add additional context in comments.

3 Comments

And if needed, here is a db fiddle for this.
I would suggest an adjustment to this fine answer. The OP should use two parameters. One for the schema and another for the table name. That way you can wrap both of them with QUOTENAME to mitigate the risk of sql injection.
Dale I see you added QUOTENAME. The problem is the OP has dbo.TableName and quotename will not work there. it would return [dbo.TableName].

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.