在SQLServer 2005函数中执行动态SQL
在SQLServer 2005函数中执行动态SQL
我会在提问之前说明,我不认为这是可以解决的。我还有一个解决办法,我可以创建一个带有OUTPUT的存储过程来完成这个任务,只是在需要使用这个校验和的部分编写代码更容易。
这段代码无法工作,因为其中使用了Exec SP_ExecuteSQL @SQL
调用。有人知道如何在函数中执行动态SQL吗?(再次强调,我不认为这是可能的。如果真的可以,请告诉我如何解决!)
Create Function Get_Checksum ( @DatabaseName varchar(100), @TableName varchar(100) ) RETURNS FLOAT AS BEGIN Declare @SQL nvarchar(4000) Declare @ColumnName varchar(100) Declare @i int Declare @Checksum float Declare @intColumns table (idRecord int identity(1,1), ColumnName varchar(255)) Declare @CS table (MyCheckSum bigint) Set @SQL = 'Insert Into @IntColumns(ColumnName)' + Char(13) + 'Select Column_Name' + Char(13) + 'From ' + @DatabaseName + '.Information_Schema.Columns (NOLOCK)' + Char(13) + 'Where Table_Name = ''' + @TableName + '''' + Char(13) + ' and Data_Type = ''int''' -- print @SQL exec sp_executeSql @SQL Set @SQL = 'Insert Into @CS(MyChecksum)' + Char(13) + 'Select ' Set @i = 1 While Exists( Select 1 From @IntColumns Where IdRecord = @i) begin Select @ColumnName = ColumnName From @IntColumns Where IdRecord = @i Set @SQL = @SQL + Char(13) + CASE WHEN @i = 1 THEN ' Sum(Cast(IsNull(' + @ColumnName + ',0) as bigint))' ELSE ' + Sum(Cast(IsNull(' + @ColumnName + ',0) as bigint))' END Set @i = @i + 1 end Set @SQL = @SQL + Char(13) + 'From ' + @DatabaseName + '..' + @TableName + ' (NOLOCK)' -- print @SQL exec sp_executeSql @SQL Set @Checksum = (Select Top 1 MyChecksum From @CS) Return isnull(@Checksum,0) END GO
在SQL Server 2005中,无法在函数中执行动态SQL语句。这是因为SQL Server将函数视为确定性的,也就是说,对于给定的输入集,函数应该始终返回相同的输出。而存储过程或动态SQL可以是非确定性的,因为它可以改变依赖的外部状态,比如表。
鉴于SQL Server函数始终是确定性的,试图绕过这一限制将是一个糟糕的主意,从未来维护的角度来看,这可能会给支持代码的人造成相当大的困惑。
SQL Server函数并非始终是确定性的,例如getdate()函数就是非确定性的(取决于语言)。
因此,如果需要执行动态SQL语句,最好使用存储过程或动态SQL。以下是一种解决方法的示例:
CREATE PROCEDURE ExecuteDynamicSQL @sqlStatement NVARCHAR(MAX) AS BEGIN EXEC sp_executesql @sqlStatement END
通过创建一个存储过程,可以将动态SQL语句作为参数传递,并使用sp_executesql过程执行该语句。这样就可以在SQL Server中执行动态SQL了。
使用存储过程来执行动态SQL语句可以解决无法在函数中执行动态SQL的问题。
在SQL Server 2005中,函数的执行是有一些限制的,其中一个限制就是无法在函数中执行动态SQL。这意味着无法在函数中使用EXECUTE或sp_executesql语句来执行动态生成的SQL语句。
这个限制的原因是函数在执行时需要保证数据的一致性和安全性,而动态SQL可能会导致数据的不一致性或安全性问题。因此,SQL Server团队决定禁止在函数中执行动态SQL。
然而,有时候我们确实需要在函数中执行动态SQL,比如根据不同的输入参数来动态生成SQL语句。在这种情况下,我们可以通过调用扩展存储过程来绕过这个限制。扩展存储过程是一种特殊的存储过程,可以在其中执行一些高级的操作,包括执行动态SQL。但是,这种方法需要更多的工作,而且可能会引入一些安全问题。
总结起来,SQL Server 2005的函数无法直接执行动态SQL是为了保证数据的一致性和安全性。然而,如果确实需要在函数中执行动态SQL,可以通过调用扩展存储过程来实现。但是需要注意,这种方法可能会带来一些额外的工作和安全问题。
参考链接:
- http://decipherinfosys.wordpress.com/2008/07/16/udf-limitations-in-sql-server/
- http://decipherinfosys.wordpress.com/2007/02/27/using-getdate-in-a-udf/
在SQL Server 2005中执行动态SQL的函数存在问题。问题的原因是函数无法在函数体内部使用INSERT EXEC这样的具有副作用的操作符。为了解决这个问题,有两种解决方法。
解决方法1:
将动态字符串从函数中返回,然后在调用函数的地方执行INSERT EXEC操作。
DECLARE @dynamicString VARCHAR(MAX) DECLARE @table TABLE () SET @dynamicString = dbo.function( ) INSERT INTO @table EXEC (@dynamicString) SELECT * FROM @table
解决方法2:
通过传递参数来调用嵌套函数。
但是这种方法不起作用,因为在函数内部使用INSERT EXEC操作符被认为是具有副作用的操作。