Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Erstellen Sie in SQL Server eine Multi-Statement Table-Valued Function (MSTVF).

Sie können eine Tabellenwertfunktion mit mehreren Anweisungen (MSTVF) in SQL Server mithilfe von T-SQL CREATE FUNCTION erstellen Syntax.

Syntax

Hier ist die offizielle Syntax für TVFs mit mehreren Anweisungen.

CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name   
( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type   
    [ = default ] [READONLY] }   
    [ ,...n ]  
  ]  
)  
RETURNS @return_variable TABLE <table_type_definition>  
    [ WITH  [ ,...n ] ]  
    [ AS ]  
    BEGIN   
        function_body   
        RETURN  
    END  
[ ; ]

Beispiel 1 – Basis-MSTVF

Hier ist ein Beispiel für eine Tabellenwertfunktion mit mehreren Anweisungen.

CREATE FUNCTION dbo.udf_PetsByName_MSTVF( @PetName varchar(70))
    RETURNS @pets TABLE (
        PetId varchar(20),
        PetName varchar(70)
    )
AS
BEGIN
    INSERT INTO @pets
    SELECT 
        CONCAT('Cat', ' ', CatId),
        CatName
    FROM dbo.Cats
    WHERE CatName = @PetName;

    INSERT INTO @pets
    SELECT 
        CONCAT('Dog', ' ', DogId),
        DogName
    FROM dbo.Dogs
    WHERE DogName = @PetName;

    IF @@ROWCOUNT = 0
    BEGIN
        INSERT INTO @pets
        VALUES (
            '',
            'There are no pets of that name.'
            )
    END

    RETURN;
END;

GO

Die Struktur der Rückgabetabelle wird zu Beginn definiert, wenn ich den @pets spezifiziere Variable. Die Abfrageergebnisse werden in @pets eingefügt Variable.

In diesem Fall muss der Funktion ein Kosename als Argument übergeben werden. Dieses Argument wird dann in den Abfragen verwendet, um die relevanten Daten zurückzugeben. Ein Multi sein -Anweisung Tabellenwertfunktion kann ich mehrere Anweisungen in die Definition der Funktion aufnehmen.

Beispiel 2 – Schemabindung hinzufügen

Es ist normalerweise eine gute Idee, Ihre Funktionen mithilfe von SCHEMABINDING an ein Schema zu binden Streit.

Dadurch wird sichergestellt, dass die zugrunde liegenden Tabellen nicht in einer Weise geändert werden können, die Ihre Funktion beeinträchtigen würde.

Ohne Schemabindung könnten die zugrunde liegenden Tabellen geändert oder sogar gelöscht werden. Dadurch könnte die Funktion unterbrochen werden.

Hier ist die gleiche Funktion, aber diesmal mit Schemabindung:

CREATE FUNCTION dbo.udf_PetsByName_MSTVF( @PetName varchar(70))
    RETURNS @pets TABLE (
        PetId varchar(20),
        PetName varchar(70)
    )
    WITH SCHEMABINDING
AS
BEGIN
    INSERT INTO @pets
    SELECT 
        CONCAT('Cat', ' ', CatId),
        CatName
    FROM dbo.Cats
    WHERE CatName = @PetName;

    INSERT INTO @pets
    SELECT 
        CONCAT('Dog', ' ', DogId),
        DogName
    FROM dbo.Dogs
    WHERE DogName = @PetName;

    IF @@ROWCOUNT = 0
    BEGIN
        INSERT INTO @pets
        VALUES (
            '',
            'There are no pets of that name.'
            )
    END

    RETURN;
END;

GO

Beachten Sie, dass ich beim Verweisen auf die Tabellen in meiner Abfrage zweiteilige Namen verwendet habe (ich habe dbo.Cats verwendet und dbo.Dogs wenn auf die Tabelle verwiesen wird, statt nur Cats oder Dogs ). Dies ist eine Voraussetzung für die Schemabindung eines Objekts. Wenn Sie versuchen, ein Objekt an ein Schema zu binden, ohne zweiteilige Namen zu verwenden, erhalten Sie eine Fehlermeldung.

Jetzt, da ich meine Funktion schemagebunden habe, erhalte ich eine Fehlermeldung, wenn ich versuche, die Tabelle, auf die in ihrer Definition verwiesen wird, zu löschen:

DROP TABLE Dogs;

Ergebnis:

Msg 3729, Level 16, State 1, Line 1
Cannot DROP TABLE 'Dogs' because it is being referenced by object 'udf_PetsByName_MSTVF'.

Übrigens passiert Folgendes, wenn ich versuche, die Funktion ohne zweiteilige Benennung zu erstellen:

CREATE FUNCTION dbo.udf_PetsByName_MSTVF( @PetName varchar(70))
    RETURNS @pets TABLE (
        PetId varchar(20),
        PetName varchar(70)
    )
    WITH SCHEMABINDING
AS
BEGIN
    INSERT INTO @pets
    SELECT 
        CONCAT('Cat', ' ', CatId),
        CatName
    FROM Cats
    WHERE CatName = @PetName;

    INSERT INTO @pets
    SELECT 
        CONCAT('Dog', ' ', DogId),
        DogName
    FROM Dogs
    WHERE DogName = @PetName;

    IF @@ROWCOUNT = 0
    BEGIN
        INSERT INTO @pets
        VALUES (
            '',
            'There are no pets of that name.'
            )
    END

    RETURN;
END;

GO

Ergebnis:

Msg 4512, Level 16, State 3, Procedure udf_PetsByName_MSTVF, Line 10
Cannot schema bind table valued function 'dbo.udf_PetsByName_MSTVF' because name 'Cats' is invalid for schema binding. Names must be in two-part format and an object cannot reference itself.

Beispiel 3 – Verschlüsselung hinzufügen

Sie können Ihre Funktionen auch mit ENCRYPTION verschlüsseln Streit.

Hier ist ein Beispiel für die Verschlüsselung der Funktion:

CREATE FUNCTION dbo.udf_PetsByName_MSTVF( @PetName varchar(70))
    RETURNS @pets TABLE (
        PetId varchar(20),
        PetName varchar(70)
    )
    WITH SCHEMABINDING, ENCRYPTION
AS
BEGIN
    INSERT INTO @pets
    SELECT 
        CONCAT('Cat', ' ', CatId),
        CatName
    FROM dbo.Cats
    WHERE CatName = @PetName;

    INSERT INTO @pets
    SELECT 
        CONCAT('Dog', ' ', DogId),
        DogName
    FROM dbo.Dogs
    WHERE DogName = @PetName;

    IF @@ROWCOUNT = 0
    BEGIN
        INSERT INTO @pets
        VALUES (
            '',
            'There are no pets of that name.'
            )
    END

    RETURN;
END;

GO

Jetzt kann ich die Definition der Funktion nicht anzeigen.

SELECT definition 
FROM sys.sql_modules
WHERE object_id = OBJECT_ID('udf_PetsByName_MSTVF');

Ergebnis:

+--------------+
| definition   |
|--------------|
| NULL         |
+--------------+

Ich erhalte auch eine Fehlermeldung, wenn ich versuche, die Definition der Funktion über Azure Data Studio zu skripten:

No script was returned when scripting as Create on object UserDefinedFunction

Beachten Sie, dass der Text einer verschlüsselten Funktion weiterhin für privilegierte Benutzer verfügbar ist, die entweder über den DAC-Port auf Systemtabellen oder direkt auf Datenbankdateien zugreifen können. Außerdem können Benutzer, die einen Debugger an den Serverprozess anhängen können, die ursprüngliche Prozedur zur Laufzeit aus dem Speicher abrufen.