Der Hauptgrund ist wahrscheinlich, dass Tabellenfunktionen eine Ergebnismenge zurückgeben, genau wie Tabellen und Ansichten. Dies bedeutet , dass sie in der verwendet werden FROMKlausel (einschließlich JOINs und APPLYs, usw.) von SELECT, UPDATEund DELETEAbfragen. Sie können jedoch in keinem dieser Kontexte eine skalare UDF verwenden.
Zweitens können Sie auch EXECUTEeine Skalar-UDF. Diese Syntax ist sehr praktisch, wenn Sie Standardwerte für Eingabeparameter angegeben haben. Nehmen Sie zum Beispiel die folgende UDF:
CREATE FUNCTION dbo.OptionalParameterTest (@Param1 INT = 1, @Param2 INT = 2)
RETURNS INT
AS
BEGIN
RETURN @Param1 + @Param2;
END;
Wenn Sie einen der Eingabeparameter als "optional" behandeln möchten, müssen Sie das DEFAULTSchlüsselwort dennoch übergeben, wenn Sie es wie eine Funktion aufrufen, da die Signatur festgelegt ist:
DECLARE @Bob1 INT;
SET @Bob1 = dbo.OptionalParameterTest(100, DEFAULT);
SELECT @Bob1;
-- Returns: 102
Wenn Sie dagegen EXECUTEdie Funktion verwenden, können Sie alle Parameter mit einem Standardwert wie bei gespeicherten Prozeduren als wirklich optional behandeln. Sie können die ersten n Parameter ohne Angabe von Parameternamen übergeben:
DECLARE @Bob2 INT;
EXEC @Bob2 = dbo.OptionalParameterTest 50;
SELECT @Bob2;
-- Returns: 52
Sie können den ersten Parameter sogar überspringen, indem Sie erneut Parameternamen angeben, genau wie bei gespeicherten Prozeduren:
DECLARE @Bob3 INT;
EXEC @Bob3 = dbo.OptionalParameterTest @Param2 = 50;
SELECT @Bob3;
-- Returns: 51
AKTUALISIEREN
Warum möchten Sie möglicherweise die EXECSyntax verwenden, um eine skalare UDF wie eine gespeicherte Prozedur aufzurufen? Gelegentlich gibt es UDFs, die sich hervorragend als UDFs eignen, da sie zu einer Abfrage hinzugefügt und über die zurückgegebenen Zeilen ausgeführt werden können. Wenn der Code in einer gespeicherten Prozedur enthalten wäre, müsste er dazu in einen Cursor eingefügt werden Iterieren Sie über eine Reihe von Zeilen. Aber dann gibt es Zeiten, in denen Sie diese Funktion für einen einzelnen Wert aufrufen möchten, möglicherweise innerhalb einer anderen UDF. Das Aufrufen einer UDF für einen einzelnen Wert kann folgendermaßen erfolgen:
SELECT dbo.UDF('some value');
In diesem Fall erhalten Sie einen Rückgabewert in einer Ergebnismenge (eine Ergebnismenge funktioniert nicht). Oder es könnte wie folgt gemacht werden:
DECLARE @Dummy INT;
SET @Dummy = dbo.UDF('some value');
In diesem Fall müssen Sie die @DummyVariable deklarieren .
Mit der EXECSyntax können Sie jedoch diese beiden Belästigungen vermeiden:
EXEC dbo.UDF 'some value';
AUCH bei skalaren UDFs werden die Ausführungspläne zwischengespeichert. Dies bedeutet, dass Parameter-Sniffing-Probleme auftreten können, wenn in der UDF Abfragen mit Ausführungsplänen vorhanden sind. In Szenarien, in denen die EXECSyntax verwendet werden kann, können Sie auch die WITH RECOMPILEOption verwenden, um den für diese Ausführung kompilierten Planwert zu ignorieren . Beispielsweise:
INSTALLIEREN:
GO
CREATE FUNCTION dbo.TestUDF (@Something INT)
RETURNS INT
AS
BEGIN
DECLARE @Ret INT;
SELECT @Ret = COUNT(*)
FROM sys.indexes si
WHERE si.[index_id] = @Something;
RETURN @Ret;
END;
GO
PRÜFUNG:
DECLARE @Val INT;
SET @Val = dbo.TestUDF(1);
SELECT @Val;
EXEC @Val = dbo.TestUDF 0 -- uses compiled value of (1)
SELECT @Val;
EXEC @Val = dbo.TestUDF 0 WITH RECOMPILE; -- uses compiled value of (0)
SELECT @Val;
EXEC @Val = dbo.TestUDF 3 -- uses compiled value of (1)
SELECT @Val;