Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Създайте функция с таблично стойности с множество оператори (MSTVF) в SQL Server

Можете да създадете функция с таблична стойност с множество изрази (MSTVF) в SQL Server, като използвате T-SQL CREATE FUNCTION синтаксис.

Синтаксис

Ето официалния синтаксис за TVF с множество изявления.

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

Пример 1 – Основен MSTVF

Ето пример за функция с таблична стойност с множество изрази.

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

Структурата на таблицата за връщане се дефинира в началото, когато посоча @pets променлива. Резултатите от заявката се вмъкват в @pets променлива.

В този случай функцията изисква да се подаде име на домашен любимец като аргумент. След това използва този аргумент в заявките, за да върне съответните данни. Да бъдеш мулти -функция със стойност на таблица, мога да включа множество изрази в дефиницията на функцията.

Пример 2 – Добавете обвързване на схема

Обикновено е добра идея да обвържете функциите си по схема, като използвате SCHEMABINDING аргумент.

Това ще гарантира, че основните таблици не могат да бъдат променяни по начин, който би засегнал вашата функция.

Без обвързване на схемата, основните таблици могат да бъдат модифицирани или дори изтрити. Правейки това може да наруши функцията.

Ето същата функция, но този път с обвързване на схема:

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

Забележете, че използвах имена от две части, когато препращах към таблиците в моята заявка (използвах dbo.Cats и dbo.Dogs при препратка към таблицата, вместо само Cats или Dogs ). Правенето на това е изискване за свързване на обект със схема. Ако се опитате да обвържете обект със схема, без да използвате имена от две части, ще получите грешка.

Сега, след като схемата обвърза функцията си, ако се опитам да пусна таблицата, посочена в нейната дефиниция, получавам грешка:

DROP TABLE Dogs;

Резултат:

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

Между другото, ето какво се случва, ако се опитам да създам функцията, без да използвам именуване от две части:

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

Резултат:

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.

Пример 3 – Добавяне на криптиране

Можете също да шифровате функциите си с помощта на ENCRYPTION аргумент.

Ето пример за криптиране на функцията:

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

Сега не мога да видя дефиницията на функцията.

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

Резултат:

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

Също така получавам съобщение за грешка, когато се опитвам да напиша дефиницията на функцията чрез Azure Data Studio:

No script was returned when scripting as Create on object UserDefinedFunction

Имайте предвид, че текстът на криптирана функция все още е достъпен за привилегировани потребители, които могат да имат достъп до системните таблици през DAC порта или директно да имат достъп до файловете на базата данни. Освен това потребителите, които могат да прикачат дебъгер към сървърния процес, могат да извличат оригиналната процедура от паметта по време на изпълнение.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Намерете колоната за разделяне за разделена таблица в SQL Server (T-SQL)

  2. Кой е най-добрият инструмент за сравняване на две бази данни на SQL Server (схема и данни)?

  3. Как да присвоя резултат от exec на sql променлива?

  4. Резултати от заявка по имейл като HTML таблица в SQL Server (T-SQL)

  5. Как да деактивирате всички ограничения на външния ключ в базата данни на SQL Server - SQL Server / TSQL урок, част 77