Pergunta

Vou prefácio a esta pergunta dizendo, eu não acho que isso pode ser resolvido. Eu também tenho uma solução alternativa, eu posso criar um procedimento armazenado com uma produção para alcançar este objetivo, é apenas mais fácil de codificar as seções onde eu preciso esta soma de verificação utilizando uma função.

Este código não vai funcionar por causa das chamadas Exec SP_ExecuteSQL @SQL. Alguém sabe como executar SQL dinâmico em uma função? (E mais uma vez, eu não acho que isso é possível. Se for embora, eu adoraria saber como contornar isso!)

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
Foi útil?

Solução

It "normalmente" não pode ser feito como SQL Server trata funciona como determinista, o que significa que para um determinado conjunto de entradas, deve sempre retornam os mesmos resultados. Um procedimento armazenado ou SQL dinâmico pode ser não-determinista, porque pode alterar o estado externo, como uma mesa, que é invocado.

Tendo em conta que nas funções de servidor SQL são sempre determinista, seria uma má idéia de uma futura perspectiva de manutenção para tentar contornar isso, pois poderia causar bastante grande confusão para quem tem de suportar o código no futuro.

Outras dicas

Aqui está a solução

Solução 1: Retornar a string dinâmica de função, então

Declare @SQLStr varchar(max) 
DECLARE @tmptable table (<columns>)
set @SQLStr=dbo.function(<parameters>)
insert into @tmptable
Exec (@SQLStr)

select * from @tmptable

Solução 2: chamar funções aninhadas passando parâmetros.

Você pode contornar este problema chamando um procedimento armazenado estendido, com todos os problemas de aborrecimento e de segurança inerentes.

http: //decipherinfosys.wordpress. com / 2008/07/16 /-UDF limitações-in sql-server /

http: //decipherinfosys.wordpress. cOM / 2007/02/27 / utilizando-getdate-in-a-UDF /

Porque funções tem que jogar bem com o otimizador de consulta, existem algumas restrições sobre eles. Esta ligação refere para um artigo que discute as limitações do UDF de em profundidade.

Obrigado a todos pelas respostas.

Ron:. FYI, Usando que irá lançar um erro

Eu concordo que não fazer o que eu originalmente planejado é a melhor solução, eu decidi ir para um caminho diferente. Minhas duas opções eram de usar sum(cast(BINARY_CHECKSUM(*) as float)) ou um parâmetro de saída de um procedimento armazenado. Após a unidade de teste de velocidade de cada um, eu decidi ir com sum(cast(BINARY_CHECKSUM(*) as float)) para obter um valor de checksum comparável para os dados de cada tabela.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top