Frage

Ich werde diese Frage Vorwort mit den Worten: Ich glaube nicht, es lösbar ist. Ich habe auch ein Problem zu umgehen, ich eine gespeicherte Prozedur mit einem OUTPUT dies zu erreichen, schaffen kann, ist es einfach leichter ist, die Abschnitte zu codieren, wo ich diese Prüfsumme brauche eine Funktion verwenden.

Dieser Code wird nicht wegen der Exec SP_ExecuteSQL @SQL Anrufe arbeiten. Wer weiß, wie dynamische SQL in einer Funktion auszuführen? (Und noch einmal, ich glaube nicht, es ist möglich. Wenn es aber ist, würde ich gerne wissen, wie um es zu bekommen!)

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
War es hilfreich?

Lösung

Es „normalerweise“ nicht getan werden kann, wie SQL Server-Funktionen als deterministisch behandelt, was bedeutet, dass für einen bestimmten Satz von Eingaben, es sollte immer die gleichen Ausgänge zurück. Eine gespeicherte Prozedur oder dynamische SQL kann nicht-deterministisch sein, weil es externen Zustand ändern kann, wie zum Beispiel einer Tabelle, die auf sich verlassen.

Da in SQL-Server-Funktionen immer deterministisch sind, wäre es eine schlechte Idee von einer künftigen Wartung Perspektive zu sein, dies zu versuchen zu umgehen, da es ziemlich große Verwirrung für jedermann dazu führen könnte, die den Code in Zukunft zu unterstützen haben.

Andere Tipps

Hier ist die Lösung

Lösung 1: Gibt die dynamische Zeichenfolge Funktion dann

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

select * from @tmptable

Lösung 2: verschachtelte Funktionen aufrufen Parameter übergeben.

Sie können dies umgehen, indem eine erweiterte gespeicherte Prozedur aufrufen, mit all den damit verbundenen Aufwand und Sicherheitsprobleme.

http: //decipherinfosys.wordpress. com / 2008/07/16 / UDF-Grenzen-in-sQL-Server /

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

Da Funktionen gut mit den Abfrage-Optimierer zu spielen haben, gibt es durchaus ein paar Einschränkungen auf sie. Dieser Link verweist zu einem Artikel, der die Grenzen der UDF in der Tiefe diskutiert.

Vielen Dank für die Antworten.

Ron. FYI, dass Verwendung einen Fehler werfen

Ich bin damit einverstanden, dass nicht zu tun, was ich ursprünglich die beste Lösung gedacht ist, habe ich beschlossen, einen anderen Weg zu gehen. Meine zwei Möglichkeiten waren sum(cast(BINARY_CHECKSUM(*) as float)) oder einen Ausgabeparameter in einer gespeicherten Prozedur verwenden. Nach Einheit Prüfgeschwindigkeit von jedem, habe ich beschlossen, mit sum(cast(BINARY_CHECKSUM(*) as float)) zu gehen, um einen vergleichbaren Prüfsummenwert für die Daten jeder Tabelle zu erhalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top