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.