sql >> Base de Datos >  >> RDS >> Sqlserver

Cree una función con valores de tabla de declaraciones múltiples (MSTVF) en SQL Server

Puede crear una función con valores de tabla de múltiples declaraciones (MSTVF) en SQL Server usando T-SQL CREATE FUNCTION sintaxis.

Sintaxis

Aquí está la sintaxis oficial para TVF de múltiples declaraciones.

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

Ejemplo 1:MSTVF básico

Este es un ejemplo de una función con valores de tabla de varias instrucciones.

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

La estructura de la tabla de retorno se define al principio cuando especifico @pets variable. Los resultados de la consulta se insertan en @pets variables.

En este caso, la función requiere que se pase un nombre de mascota como argumento. Luego usa este argumento en las consultas para devolver los datos relevantes. Ser un multi función con valores de tabla de declaraciones, puedo incluir varias declaraciones en la definición de la función.

Ejemplo 2:Agregar enlace de esquema

Por lo general, es una buena idea vincular sus funciones mediante el uso de SCHEMABINDING argumento.

Hacer esto asegurará que las tablas subyacentes no se puedan cambiar de una manera que afecte su función.

Sin vinculación de esquema, las tablas subyacentes podrían modificarse o incluso eliminarse. Hacer esto podría romper la función.

Aquí está la misma función, pero esta vez con enlace de esquema:

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

Observe que utilicé nombres de dos partes al hacer referencia a las tablas en mi consulta (utilicé dbo.Cats y dbo.Dogs al hacer referencia a la tabla, en lugar de solo Cats o Dogs ). Hacer esto es un requisito para el enlace de esquema de un objeto. Si intenta enlazar un objeto mediante un esquema sin usar nombres de dos partes, obtendrá un error.

Ahora que he vinculado el esquema a mi función, si trato de eliminar la tabla a la que se hace referencia en su definición, aparece un error:

DROP TABLE Dogs;

Resultado:

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

Por cierto, esto es lo que sucede si intento crear la función sin usar nombres de dos partes:

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

Resultado:

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.

Ejemplo 3:agregar cifrado

También puede encriptar sus funciones usando ENCRYPTION argumento.

Aquí hay un ejemplo de encriptación de la función:

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

Ahora no puedo ver la definición de la función.

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

Resultado:

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

También recibo un mensaje de error cuando intento escribir la definición de la función a través de Azure Data Studio:

No script was returned when scripting as Create on object UserDefinedFunction

Tenga en cuenta que el texto de una función encriptada todavía está disponible para usuarios privilegiados que pueden acceder a las tablas del sistema a través del puerto DAC o acceder directamente a los archivos de la base de datos. Además, los usuarios que pueden adjuntar un depurador al proceso del servidor pueden recuperar el procedimiento original de la memoria en tiempo de ejecución.