SQL无效标识符错误
我有一个执行select语句的函数。当我尝试执行此select语句时,该语句返回一个值并将其设置为一个变量,我的函数会崩溃,出现以下错误: Msg 203,16级,状态2,程序信息\u GetWholeNumber,第20行SQL无效标识符错误,sql,sql-server,sql-server-2008-r2,Sql,Sql Server,Sql Server 2008 R2,我有一个执行select语句的函数。当我尝试执行此select语句时,该语句返回一个值并将其设置为一个变量,我的函数会崩溃,出现以下错误: Msg 203,16级,状态2,程序信息\u GetWholeNumber,第20行 名称“选择最大长度(铸造(地板([pcom\U audit\u cant\u con])作为 VARCHAR(38)))作为一个整体,Auditorias.prod\u com\u audit“不是 有效标识符 如果我复制并粘贴select语句,效果会很好。。。因此,这不是
名称“选择最大长度(铸造(地板([pcom\U audit\u cant\u con])作为 VARCHAR(38)))作为一个整体,Auditorias.prod\u com\u audit“不是 有效标识符 如果我复制并粘贴select语句,效果会很好。。。因此,这不是选择,它与我的执行有关。。。无论如何,这是我的函数代码
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
我现在得到这个错误:
Msg 1087,第16级,状态1,第1行
必须声明表变量“@TBL”
在我看来这似乎是正确的,因为变量不是在@PARAM变量中声明的。。。我在这里遗漏了什么吗?拉马克是对的。不能在函数中执行存储过程(或任何能够更新、插入、删除的操作)
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
函数应该是只读的
你可能想考虑使用一个存储过程代替你的函数。
< P> Lamak是正确的。不能在函数中执行存储过程(或任何能够更新、插入、删除的操作)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
函数应该是只读的
你可能想考虑使用一个存储过程代替你的函数。
< P>你既不能直接从一个Exchange语句分配,也不能直接从一个<代码> Exc< /Cord>d动态SQL中分配变量(超出范围)。这也不应该真正从函数中调用,因为SQL期望函数是确定性的,而事实并非如此(事实上,即使修复了错误,它也可能不起作用)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
假设更改了调用此代码的方式,则需要知道如何从动态sql中获取值。如果要从动态SQL字符串传递变量,则必须将EXEC SP\u 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;
在本例中,我们将设置一个参数定义和一个输出参数。一般来说,sp_executesql
是调用动态sql的首选方法,因为它可以参数化,这既可以通过避免直接连接sql来提高安全性,也可以在sql完全参数化时允许计划重用
我还应该补充一个强制性的警告,即无论是现在还是将来,您都不应该像对待sql注入那样漫不经心地构建动态sql。我知道您不能参数化特定的查询,但至少您应该在列名上使用QUOTENAME()
,而不是对[]
进行硬编码
请在此处阅读有关sp_executesql的更多信息:
有关
QUOTENAME()
的更多信息,请参见:您既不能直接从EXEC语句赋值,也不能直接从EXEC
d动态SQL内部赋值变量(超出范围)。这也不应该真正从函数中调用,因为SQL期望函数是确定性的,而事实并非如此(事实上,即使修复了错误,它也可能不起作用)
假设更改了调用此代码的方式,则需要知道如何从动态sql中获取值。如果要从动态SQL字符串传递变量,则必须将EXEC SP\u 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;
在本例中,我们将设置一个参数定义和一个输出参数。一般来说,sp_executesql
是调用动态sql的首选方法,因为它可以参数化,这既可以通过避免直接连接sql来提高安全性,也可以在sql完全参数化时允许计划重用
我还应该补充一个强制性的警告,即无论是现在还是将来,您都不应该像对待sql注入那样漫不经心地构建动态sql。我知道您不能参数化特定的查询,但至少您应该在列名上使用QUOTENAME()
,而不是对[]
进行硬编码
请在此处阅读有关sp_executesql的更多信息:
更多关于
QUOTENAME()
的信息,请点击此处:您不能在计算机上使用EXEC
function@Lamak在我的例子中,由于select语句是动态的…,我将如何执行它?您仍然不能使用EXECUTE
或sp_executesql
或调用函数中的任何其他存储过程。为什么这需要是一个函数?您不能在计算机上使用EXEC
function@Lamak在我的例子中,由于select语句是动态的…,我将如何执行它?您仍然不能使用EXECUTE
或sp_executesql
或调用函数中的任何其他存储过程。为什么这需要是一个函数?我刚刚更新了我的问题,我在尝试你的建议,但现在又出现了一个错误。你知道为什么吗?@Lord Link你不能像那样参数化表和列。在调用sp_executesql
so:SET@SQL=N'SELECT@WHOLE_NOOUT=MAX(LEN(CAST(FLOOR('+QUOTENAME(@COLUMN)+')AS VARCHAR(38)))之前,您需要将它们构建到SQL字符串中,然后从'+QUOTENAME(@TABLE)
的参数定义中删除它们。这样,您将只参数化输出变量。好吧,这似乎做了一些正确的事情,因为我没有得到一个错误。。。我的问题被卡住了,但我会检查一下,看看我是否能找出原因。。。谢谢你的帮助,谢谢你,很抱歉我反应迟钝