sql >> データベース >  >> RDS >> Sqlserver

SQL Serverでマルチステートメントテーブル値関数(MSTVF)を作成する

    T-SQL CREATE FUNCTIONを使用して、SQL Serverでマルチステートメントテーブル値関数(MSTVF)を作成できます。 構文。

    構文

    マルチステートメント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
    

    クエリでテーブルを参照するときに2つの部分からなる名前を使用したことに注意してください(dbo.Catsを使用しました) およびdbo.Dogs Catsだけでなく、テーブルを参照する場合 またはDogs )。これを行うことは、オブジェクトをバインドするスキーマの要件です。 2つの部分からなる名前を使用せずにオブジェクトをスキーマバインドしようとすると、エラーが発生します。

    関数をスキーマバインドしたので、その定義で参照されているテーブルを削除しようとすると、エラーが発生します:

    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'.
    

    ちなみに、2つの部分からなる名前を使用せずに関数を作成しようとすると、次のようになります。

    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. SQL Server:5列にわたる動的ピボット

    2. Postgres:制約がまだ存在しない場合は制約を追加します

    3. SQL Server Management Studio(SSMS)で上位X行を編集して上位X行を選択するための値を変更する方法-SQL Server/TSQLチュートリアルパート20

    4. 楽観的ロックと悲観的ロック