我有一个执行select语句的函数。当我尝试执行这个返回单个值并将其设置为变量的select语句时,我的函数崩溃并出现以下错误:
Msg 203,Level 16,State 2,Procedure Info_GetWholeNumber,Line 20
名称'SELECT MAX(LEN(CAST(FLOOR([pcom_audit_cant_con])AS VARCHAR(38))))AS Audoleias.prod_com_audit的WHOLE_NO'不是 有效的标识符。
如果我复制并粘贴那个select语句就可以正常工作......因此它不是选择它与我的EXEC有关...反正这里是我的函数代码......
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
如果有人有任何想法我可以解决这个问题,我真的很感激帮助!提前谢谢!
更新
好的,所以我试图按照说明使用sp_executesql函数,我将粘贴新函数。
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
我现在收到此错误:
消息1087,级别16,状态1,第1行 必须声明表变量“@TBL”
在我看来这似乎是正确的,因为变量不是在@PARAM变量中声明的...我在这里遗漏了什么?
答案 0 :(得分:4)
既不能直接从EXEC语句中分配,也不能直接从EXEC
动态SQL内部分配变量(它超出范围)。这也不应该从函数中调用,因为SQL期望函数是确定性的,而事实上并非如此(事实上,即使您修复了错误,它仍然可能无法正常工作。)
假设你改变了调用这段代码的方式,你需要知道如何从动态sql中获取你的价值。如果要从动态SQL字符串传递变量,则必须将EXEC SP_ExecuteSQL
与输出参数一起使用。
这是一个简单的例子:
DECLARE @whole_no int;
DECLARE @SQL nvarchar(500);
DECLARE @Parms nvarchar(500);;
SET @SQL = N'SELECT @whole_noOUT = 1';
SET @Parms = N'@whole_noOUT int OUTPUT';
EXECUTE sp_executesql @SQL, @Parms, @whole_noOUT=@whole_no OUTPUT;
SELECT @WHOLE_NO;
在这个例子中,我们设置了一个param定义和一个输出参数。通常,sp_executesql
是调用动态sql的首选方法,因为它可以参数化,既可以通过避免直接连接sql来提高安全性,也可以在sql完全参数化时允许计划重用。
我还应该添加强制性警告,即你现在或将来都不应该像现在或未来一样打开自己的SQL注入方式来构建动态sql。我们了解到您无法对您的特定查询进行参数化,但至少您应该在列名上使用QUOTENAME()
而不是对[]
进行硬编码。
点击此处sp_executesql
了解详情:http://msdn.microsoft.com/en-us/library/ms188001.aspx
还有更多关于QUOTENAME()
的信息:http://msdn.microsoft.com/en-us/library/ms176114.aspx
答案 1 :(得分:0)
Lamak是对的。您无法在函数内执行存储过程(或任何能够进行更新,插入,删除的操作)。
函数应该是只读的。
您可能需要考虑使用存储过程代替您的功能。