sql >> Databasteknik >  >> RDS >> Sqlserver

Skapa en Multi-Statement Table-Valued Function (MSTVF) i SQL Server

Du kan skapa en multi-statement table-valued function (MSTVF) i SQL Server med T-SQL CREATE FUNCTION syntax.

Syntax

Här är den officiella syntaxen för TVF:er med flera påståenden.

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  
[ ; ]

Exempel 1 – Grundläggande MSTVF

Här är ett exempel på en tabellvärderad funktion med flera påståenden.

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

Returtabellens struktur definieras i början när jag anger @pets variabel. Frågeresultaten infogas i @pets variabel.

I det här fallet kräver funktionen att ett husdjursnamn skickas in som ett argument. Den använder sedan detta argument i frågorna för att returnera relevant data. Att vara en multi -sats tabellvärderad funktion, jag kan inkludera flera satser i funktionens definition.

Exempel 2 – Lägg till schemabindning

Det är vanligtvis en bra idé att schemabinda dina funktioner genom att använda SCHEMABINDING argument.

Genom att göra detta säkerställer du att de underliggande tabellerna inte kan ändras på ett sätt som skulle påverka din funktion.

Utan schemabindning kan de underliggande tabellerna ändras eller till och med raderas. Om du gör detta kan funktionen bryta.

Här är samma funktion, men den här gången med schemabindning:

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

Observera att jag använde tvådelade namn när jag refererade till tabellerna i min fråga (jag använde dbo.Cats och dbo.Dogs när du hänvisar till tabellen, istället för bara Cats eller Dogs ). Att göra detta är ett krav för att schemabinda ett objekt. Om du försöker schemalägga ett objekt utan att använda tvådelade namn får du ett felmeddelande.

Nu när jag har schemalagt min funktion, om jag försöker ta bort tabellen som refereras till i dess definition, får jag ett felmeddelande:

DROP TABLE Dogs;

Resultat:

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

Förresten, här är vad som händer om jag försöker skapa funktionen utan att använda tvådelad namngivning:

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

Resultat:

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.

Exempel 3 – Lägg till kryptering

Du kan också kryptera dina funktioner med ENCRYPTION argument.

Här är ett exempel på kryptering av funktionen:

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

Nu kan jag inte se funktionens definition.

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

Resultat:

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

Jag får också ett felmeddelande när jag försöker skripta funktionens definition via Azure Data Studio:

No script was returned when scripting as Create on object UserDefinedFunction

Observera att en krypterad funktions text fortfarande är tillgänglig för privilegierade användare som antingen kan komma åt systemtabeller via DAC-porten eller direkt komma åt databasfiler. Användare som kan koppla en debugger till serverprocessen kan också hämta den ursprungliga proceduren från minnet vid körning.


  1. Hur fixar man fel i pg_dump-versionen?

  2. Vi presenterar uppspelning – ny tidpunktsdiagnos för Spotlight Cloud

  3. Korstabellbegränsningar i PostgreSQL

  4. Hur man skapar ett navigeringsformulär i Microsoft Access