Domanda

Prefarrò questa domanda dicendo: non penso che sia risolvibile. Ho anche una soluzione alternativa, posso creare una procedura memorizzata con un OUTPUT per raggiungere questo obiettivo, è solo più facile codificare le sezioni in cui ho bisogno di questo checksum usando una funzione.

Questo codice non funzionerà a causa delle chiamate Exec SP_ExecuteSQL @SQL . Qualcuno sa come eseguire SQL dinamico in una funzione? (e ancora una volta, non credo sia possibile. Se è così, mi piacerebbe sapere come aggirarlo!)

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
È stato utile?

Soluzione

Si " ordinariamente " non può essere eseguito poiché SQL Server considera le funzioni come deterministiche, il che significa che per un determinato set di input, dovrebbe sempre restituire gli stessi output. Una procedura memorizzata o sql dinamico può essere non deterministico perché può cambiare lo stato esterno, ad esempio una tabella, su cui si fa affidamento.

Dato che le funzioni del server SQL sono sempre deterministiche, sarebbe una cattiva idea dal punto di vista della manutenzione futura tentare di aggirare ciò poiché potrebbe causare confusione abbastanza grande per chiunque debba supportare il codice in futuro.

Altri suggerimenti

Ecco la soluzione

Soluzione 1: Restituisce la stringa dinamica da Funzione quindi

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

select * from @tmptable

Soluzione 2: chiama le funzioni nidificate passando parametri.

Puoi aggirare il problema chiamando una stored procedure estesa, con tutte le seccature e i problemi di sicurezza dell'operatore

http: //decipherinfosys.wordpress. com / 2008/07/16 / UDF-limiti-in-sql server /

http: //decipherinfosys.wordpress. com / 2007/02/27 / usando-getdate-in-a-UDF /

Poiché le funzioni devono funzionare bene con Query Optimizer, esistono alcune limitazioni. Questo link si riferisce a un articolo che discute in dettaglio i limiti dell'UDF.

Grazie a tutti per le risposte.

Ron: Cordiali saluti, Usarlo genererà un errore.

Sono d'accordo sul fatto che non fare ciò che inizialmente intendevo fosse la soluzione migliore, ho deciso di seguire una strada diversa. Le mie due scelte erano di usare sum (cast (BINARY_CHECKSUM (*) come float)) o un parametro di output in una procedura memorizzata. Dopo la velocità di test unitaria di ciascuno, ho deciso di scegliere sum (cast (BINARY_CHECKSUM (*) come float)) per ottenere un valore di checksum comparabile per i dati di ciascuna tabella.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top