値が破棄されることを意図していないと仮定し6
ます(破棄された場合は、ロジックを説明してください)。また、テーブル2のすべての行をテーブル2に挿入したいとします。
INSERT dbo.Table3(table1_ID, table2_ID)
SELECT @ID, ID
FROM dbo.Table2
-- WHERE ID <> 6???
;
IDのリストが実際にCSVである場合、次のようになります。
最初にSplit関数を作成します(整数の代わりに文字列を出力することを除いて、ここで説明するいくつかの選択肢)。
CREATE FUNCTION dbo.SplitInts
(
@List VARCHAR(MAX),
@Delimiter VARCHAR(255)
)
RETURNS @t TABLE(Item INT)
AS
BEGIN
INSERT @t(Item) SELECT CONVERT(INT, SUBSTRING(@List, Number,
CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number))
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects) AS n(Number)
WHERE Number <= CONVERT(INT, LEN(@List))
AND SUBSTRING(@Delimiter + @List, Number, 1) = @Delimiter;
RETURN;
END
GO
これで、ストアドプロシージャは次のように簡単に言うことができます。
CREATE PROCEDURE dbo.whatever
@ID INT,
@IDs VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.Table3(table1_ID, table2_ID)
SELECT @ID, Item
FROM dbo.SplitInts(@IDs, ',');
END
GO
ただし、SQL Server 2008以降を使用していて、このコンマ区切りIDのリストがアプリケーション(DataTableまたはその他のセットなど)からのものである場合は、テーブル値パラメーターを使用して、分割の必要性を回避できます。
CREATE TYPE dbo.SetOfIntegers
( Number INT );
GO
CREATE PROCEDURE dbo.whatever
@ID INT,
@IDs dbo.SetOfIntegers READONLY
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.Table3(table1_ID, table2_ID)
SELECT @ID, Item
FROM @IDs;
END
GO
次に、CSVを文字列として渡すのではなくDataTable
、として渡すようにC#コードを変更する必要があります。SqlDbType.Structured
詳細はこちら:
http://www.sqlperformance.com/2012/08/t-sql-queries/splitting-strings-now-with-less-t-sql