我将在这个问题的序言中说,我不认为它是可以解决的.我也有一个解决方法,我可以用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
Rob.. 15
它"通常"无法完成,因为SQL Server将函数视为确定性,这意味着对于给定的输入集,它应始终返回相同的输出.存储过程或动态sql可以是非确定性的,因为它可以更改依赖的外部状态,例如表.
鉴于在SQL服务器中,函数总是具有确定性,从未来的维护角度来看,试图规避这一点并不是一个坏主意,因为它可能会给将来必须支持代码的任何人带来相当大的混淆.
它"通常"无法完成,因为SQL Server将函数视为确定性,这意味着对于给定的输入集,它应始终返回相同的输出.存储过程或动态sql可以是非确定性的,因为它可以更改依赖的外部状态,例如表.
鉴于在SQL服务器中,函数总是具有确定性,从未来的维护角度来看,试图规避这一点并不是一个坏主意,因为它可能会给将来必须支持代码的任何人带来相当大的混淆.
这是解决方案
解决方案1: 从Function返回动态字符串
Declare @SQLStr varchar(max) DECLARE @tmptable table () set @SQLStr=dbo.function( ) insert into @tmptable Exec (@SQLStr) select * from @tmptable
解决方案2: 通过传递参数调用嵌套函数.