TSQL で文字列を分割して処理する方法が必要です。これを行うには多くの方法があります。この記事では、ほぼすべての方法の長所と短所について説明します。
SQL Server 2000 以前の配列とリスト
分割関数を作成する必要があります。これは、分割機能を使用する方法です。
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
[TSQL で文字列を分割する数値テーブル アプローチを好む]( SQL Server 2000 以前の配列とリスト) ですが、SQL Server で文字列を分割する方法は多数あります。それぞれの長所と短所を説明している前のリンクを参照してください。 .
Numbers
Numbers Table メソッドを機能させるには、1 から 10,000 までの行を含むテーブルを作成する、この 1 回限りのテーブル設定を行う必要があります。
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
Numbers テーブルを設定したら、次の分割関数を作成します。
CREATE FUNCTION inline_split_me (@SplitOn char(1),@param varchar(7998)) RETURNS TABLE AS
RETURN(SELECT substring(@SplitOn + @param + ',', Number + 1,
charindex(@SplitOn, @SplitOn + @param + @SplitOn, Number + 1) - Number - 1)
AS Value
FROM Numbers
WHERE Number <= len(@SplitOn + @param + @SplitOn) - 1
AND substring(@SplitOn + @param + @SplitOn, Number, 1) = @SplitOn)
GO
CSV 文字列を簡単にテーブルに分割して結合できるようになりました。
select * from dbo.inline_split_me(';','1;22;333;4444;;') where LEN(Value)>0
出力:
Value
----------------------
1
22
333
4444
(4 row(s) affected)
新しいテーブルを作成するには、これを使用します:
--set up tables:
create table TableA (id int, commodities varchar(8000))
INSERT TableA VALUES (1135,'fish,eggs,meat')
INSERT TableA VALUES (1127,'flour,oil')
Create table TableB (id int, commodities varchar(8000))
--populate TableB
INSERT TableB
(id, commodities)
SELECT
a.id,c.value
FROM TableA a
CROSS APPLY dbo.inline_split_me(',',a.commodities) c
--show tableB contents:
select * from TableB
出力:
id commodities
----------- -------------
1135 fish
1135 eggs
1135 meat
1127 flour
1127 oil
(5 row(s) affected)
SQL Server 2000 がサポートしていないことについての Conrad Frix のコメントの後に編集CROSS APPLY
これは同じことを行います:
INSERT TableB
(id, commodities)
SELECT
a.id,NullIf(SubString(',' + a.commodities + ',' , number , CharIndex(',' , ',' + a.commodities + ',' , number) - number) , '')
FROM TableA a
INNER JOIN Numbers n ON 1=1
WHERE SubString(',' + a.commodities + ',' , number - 1, 1) = ','
AND CharIndex(',' , ',' + a.commodities + ',' , number) - number > 0
AND number <= Len(',' + a.commodities + ',')
@Rup による回答のリンクのコードに基づいています。これは基本的に関数呼び出しを削除し、(同様の Numbers テーブル分割を使用して) メイン クエリで分割を行うため、CROSS APPLY
.