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

パラメータの配列をストアド プロシージャに渡す

    Sql Server 2008 以降を使用している場合は、リスト データをストアド プロシージャに渡すたびにシリアル化および逆シリアル化する代わりに、テーブル値パラメーター (TVP) と呼ばれるものを使用できます。

    遊び場として機能する簡単なスキーマを作成することから始めましょう:

    CREATE DATABASE [TestbedDb]
    GO
    
    
    USE [TestbedDb]
    GO
    
        /* First, setup the sample program's account & credentials*/
    CREATE LOGIN [testbedUser] WITH PASSWORD=N'µ×?
    ?S[°¿Q­¥½q?_Ĭ¼Ð)3õļ%dv', DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON
    GO
    
    CREATE USER [testbedUser] FOR LOGIN [testbedUser] WITH DEFAULT_SCHEMA=[dbo]
    GO
    
    EXEC sp_addrolemember N'db_owner', N'testbedUser'
    GO
    
    
        /* Now setup the schema */
    CREATE TABLE dbo.Table1 ( t1Id INT NOT NULL PRIMARY KEY );
    GO
    
    INSERT INTO dbo.Table1 (t1Id)
    VALUES
        (1),
        (2),
        (3),
        (4),
        (5),
        (6),
        (7),
        (8),
        (9),
        (10);
    GO
    

    スキーマとサンプル データが用意できたので、TVP ストアド プロシージャを作成する準備が整いました。

    CREATE TYPE T1Ids AS Table (
            t1Id INT
    );
    GO
    
    
    CREATE PROCEDURE dbo.FindMatchingRowsInTable1( @Table1Ids AS T1Ids READONLY )
    AS
    BEGIN
            SET NOCOUNT ON;
    
            SELECT Table1.t1Id FROM dbo.Table1 AS Table1
            JOIN @Table1Ids AS paramTable1Ids ON Table1.t1Id = paramTable1Ids.t1Id;
    END
    GO
    

    スキーマと API の両方を用意したら、次のようにプログラムから TVP ストアド プロシージャを呼び出すことができます。

            // Curry the TVP data
            DataTable t1Ids = new DataTable( );
            t1Ids.Columns.Add( "t1Id",
                               typeof( int ) );
    
            int[] listOfIdsToFind = new[] {1, 5, 9};
            foreach ( int id in listOfIdsToFind )
            {
                t1Ids.Rows.Add( id );
            }
            // Prepare the connection details
            SqlConnection testbedConnection =
                    new SqlConnection(
                            @"Data Source=.\SQLExpress;Initial Catalog=TestbedDb;Persist Security Info=True;User ID=testbedUser;Password=letmein12;Connect Timeout=5" );
    
            try
            {
                testbedConnection.Open( );
    
                // Prepare a call to the stored procedure
                SqlCommand findMatchingRowsInTable1 = new SqlCommand( "dbo.FindMatchingRowsInTable1",
                                                                      testbedConnection );
                findMatchingRowsInTable1.CommandType = CommandType.StoredProcedure;
    
                // Curry up the TVP parameter
                SqlParameter sqlParameter = new SqlParameter( "Table1Ids",
                                                              t1Ids );
                findMatchingRowsInTable1.Parameters.Add( sqlParameter );
    
                // Execute the stored procedure
                SqlDataReader sqlDataReader = findMatchingRowsInTable1.ExecuteReader( );
    
                while ( sqlDataReader.Read( ) )
                {
                    Console.WriteLine( "Matching t1ID: {0}",
                                       sqlDataReader[ "t1Id" ] );
                }
            }
            catch ( Exception e )
            {
                Console.WriteLine( e.ToString( ) );
            }
      /* Output:
       * Matching t1ID: 1
       * Matching t1ID: 5
       * Matching t1ID: 9
       */
    

    Entity Framework などのより抽象的な API を使用してこれを行うには、おそらく痛みの少ない方法があります。しかし、現時点では自分の目で確かめる時間はありません。



    1. SQL Server で ISNULL() を使用しているときにパフォーマンスの問題はありますか?

    2. #1242-サブクエリが複数の行を返す-mysql

    3. Prismaの一意キーに複数のフィールドを使用する

    4. postgresqlのIF-THEN-ELSEステートメント