I have a function which executes a select statement. When I attempt to execute this select statement which returns a single value and sets it to a variable my function crashes with the following error:
Msg 203, Level 16, State 2, Procedure Info_GetWholeNumber, Line 20
The name ‘SELECT MAX(LEN(CAST(FLOOR([pcom_audit_cant_con]) AS
VARCHAR(38)))) AS WHOLE_NO FROM Auditorias.prod_com_audit’ is not a
valid identifier.
If I copy and paste that select statement it works fine… therefore it’s not the select it has something to do with my EXEC… anyways here’s my functions code…
ALTER FUNCTION [dbo].[Info_GetWholeNumber]
(
@TABLE VARCHAR(MAX)
, @COLUMN VARCHAR(MAX)
)
RETURNS INT
AS
BEGIN
-- Declare the return variable here
DECLARE @WHOLE_NO INT
-- Add the T-SQL statements to compute the return value here
DECLARE @SQL VARCHAR(MAX)
SET @SQL = 'SELECT MAX(LEN(CAST(FLOOR([' + @COLUMN + ']) AS VARCHAR(38))))
AS WHOLE_NO FROM ' + @TABLE
EXEC @WHOLE_NO = @SQL
-- Return the result of the function
RETURN @WHOLE_NO
END
If anyone has any ideas how I can fix this I’d really appreciate the help! Thanks in advance!
UPDATES:
OK so im attempting to use the sp_executesql function as stated and i am going to paste the new function.
ALTER FUNCTION [dbo].[Info_GetWholeNumber]
(
@TABLE VARCHAR(MAX)
, @COLUMN VARCHAR(MAX)
)
RETURNS INT
AS
BEGIN
DECLARE @WHOLE_NO INT
DECLARE @SQL NVARCHAR(MAX)
DECLARE @PARAMS NVARCHAR(MAX)
SET @SQL = N'SELECT @WHOLE_NOOUT = MAX(LEN(CAST(FLOOR(@COL) AS VARCHAR(38)))) FROM @TBL'
SET @PARAMS = N'@COL VARCHAR(MAX), @TBL VARCHAR(MAX), @WHOLE_NOOUT INT OUTPUT'
EXECUTE sp_executesql @SQL, @PARAMS, @COL = @COLUMN, @TBL = @TABLE, @WHOLE_NOOUT = @WHOLE_NO OUTPUT;
-- Return the result of the function
RETURN @WHOLE_NO
END
I am now getting this error:
Msg 1087, Level 16, State 1, Line 1
Must declare the table variable “@TBL”
Which in my opinion seems correct since the variables arent declared other than in the @PARAM variable… Am I missing something here?
You can neither assign directly from an EXEC statement, nor can you directly assign a variable from inside an
EXECd dynamic SQL (it’s out of scope). This also shouldn’t really be called from a function as SQL expects functions to be deterministic and this really isn’t (In fact even if you fix your error, it still probably won’t work.)Assuming you change how you’re calling this code you’ll need to know how to get your value from the dynamic sql. If you want to pass a variable from a dynamic SQL string, you must use
EXEC SP_ExecuteSQLwith an output parameter.Here is a simple example:
In this example, we’re setting a param definition, and an output parameter. In general,
sp_executesqlis the preferred method for calling dynamic sql since it can be parameterized which both increases security by avoiding the need to concatenating sql directly, but also allows plan reuse when your sql is fully parameterized.I should also add the obligatory warning that your really shouldn’t be building dynamic sql in such a cavalier manner as you open yourself up to SQL injection, either now or in the future. I understand that you cannot parameterize your particular query but, at the very least, you should be using
QUOTENAME()on your column name instead of hardcoding the[].Read more on
sp_executesqlhere: http://msdn.microsoft.com/en-us/library/ms188001.aspxAnd more on
QUOTENAME()here: http://msdn.microsoft.com/en-us/library/ms176114.aspx