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

ここでテーブル値パラメーターを使用する必要がありますか?

    はい、テーブル値パラメーターを使用します。最初に型を作成します:

    CREATE TYPE dbo.StudentIDs(ID INT PRIMARY KEY);
      

    これで、プロシージャでこれを使用できるようになりました (ネストされた IN を変更したことに注意してください) 適切な結合へのクエリ):

    CREATE PROCEDURE dbo.MarkStudentsAsDeleted
      @IDs dbo.StudentIDs READONLY
    AS
    BEGIN
      SET NOCOUNT ON;
    
      UPDATE s SET IsDeleted = 1
        FROM dbo.Students AS s
        INNER JOIN dbo.Class AS c
        ON s.StudentId = c.StudentId
        INNER JOIN dbo.ClassValueTable AS ct
        ON c.PassId = ct.Id
        WHERE ct.IsDeleted <> 1
        AND EXISTS (SELECT 1 FROM @IDs WHERE StudentID = s.StudentID);
    END 
    GO
      

    C# コードは DataTable を渡すか、コンマ区切りのリストではなく、activeIds のコレクションを組み立てます。

    DataTable dt = new DataTable();
    dt.Columns.Add("ID", typeof(int));
    dt.Rows.Add(1);
    dt.Rows.Add(2);
    dt.Rows.Add(3);
    dt.Rows.Add(4);
    
    ... open connection etc. ...
    
    SqlCommand cmd = new SqlCommand("dbo.MarkStudentsAsDeleted", conn);
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter tvp1 = cmd.Parameters.AddWithValue("@IDs", dt);
    tvp1.SqlDbType = SqlDbType.Structured;
    cmd.ExecuteNonQuery();
    
    ... close, dispose, etc. ...
      

    ストアド プロシージャに必ず文字列を渡したい場合は、分割関数を使用する必要があります。例:

    CREATE FUNCTION dbo.SplitInts
    (
       @List       VARCHAR(MAX),
       @Delimiter  VARCHAR(255) = ','
    )
    RETURNS TABLE
    WITH SCHEMABINDING 
    AS
      RETURN 
      (  
        SELECT [value] = y.i.value('(./text())[1]', 'int')
        FROM 
        ( 
          SELECT x = CONVERT(XML, '<i>' 
            + REPLACE(@List, @Delimiter, '</i><i>') 
            + '</i>').query('.')
        ) AS a CROSS APPLY x.nodes('i') AS y(i)
      );
    GO
      

    ストアド プロシージャは次のようになります。

    CREATE PROCEDURE dbo.MarkStudentsAsDeleted
      @IDs VARCHAR(MAX)
    AS
    BEGIN
      SET NOCOUNT ON;
    
      UPDATE s SET IsDeleted = 1
        FROM dbo.Students AS s
        INNER JOIN dbo.Class AS c
        ON s.StudentId = c.StudentId
        INNER JOIN dbo.ClassValueTable AS ct
        ON c.PassId = ct.Id
        WHERE ct.IsDeleted <> 1
        AND EXISTS (SELECT 1 FROM dbo.SplitInts(@IDs, ',') WHERE Item = s.StudentID);
    END 
    GO
      


    1. NOT IN、OUTER APPLY、LEFT OUTER JOIN、EXCEPT、またはNOT EXISTSを使用する必要がありますか?

    2. Rails、開発用sqlite3データベースから本番用MySQLデータベースにデータを移行する方法は?

    3. ORA-00910:指定された長さがデータ型に対して長すぎます

    4. この関数にテーブルパラメータを渡すにはどうすればよいですか?