これは、
IF EXISTS (
SELECT 1
FROM dbo.sysobjects
WHERE id = object_id(N'[dbo].[ParseString]')
AND xtype in (N'FN', N'IF', N'TF'))
BEGIN
DROP FUNCTION [dbo].[ParseString]
END
GO
CREATE FUNCTION dbo.ParseString (@String VARCHAR(8000), @Delimiter VARCHAR(10))
RETURNS TABLE
AS
/*******************************************************************************************************
* dbo.ParseString
*
* Creator: magicmike
* Date: 9/12/2006
*
*
* Outline: A set-based string tokenizer
* Takes a string that is delimited by another string (of one or more characters),
* parses it out into tokens and returns the tokens in table format. Leading
* and trailing spaces in each token are removed, and empty tokens are thrown
* away.
*
*
* Usage examples/test cases:
Single-byte delimiter:
select * from dbo.ParseString2('|HDI|TR|YUM|||', '|')
select * from dbo.ParseString2('HDI| || TR |YUM', '|')
select * from dbo.ParseString2(' HDI| || S P A C E S |YUM | ', '|')
select * from dbo.ParseString2('HDI|||TR|YUM', '|')
select * from dbo.ParseString2('', '|')
select * from dbo.ParseString2('YUM', '|')
select * from dbo.ParseString2('||||', '|')
select * from dbo.ParseString2('HDI TR YUM', ' ')
select * from dbo.ParseString2(' HDI| || S P A C E S |YUM | ', ' ') order by Ident
select * from dbo.ParseString2(' HDI| || S P A C E S |YUM | ', ' ') order by StringValue
Multi-byte delimiter:
select * from dbo.ParseString2('HDI and TR', 'and')
select * from dbo.ParseString2('Pebbles and Bamm Bamm', 'and')
select * from dbo.ParseString2('Pebbles and sandbars', 'and')
select * from dbo.ParseString2('Pebbles and sandbars', ' and ')
select * from dbo.ParseString2('Pebbles and sand', 'and')
select * from dbo.ParseString2('Pebbles and sand', ' and ')
*
*
* Notes:
1. A delimiter is optional. If a blank delimiter is given, each byte is returned in it's own row (including spaces).
select * from dbo.ParseString3('|HDI|TR|YUM|||', '')
2. In order to maintain compatibility with SQL 2000, ident is not sequential but can still be used in an order clause
If you are running on SQL2005 or later
SELECT Ident, StringValue FROM
with
SELECT Ident = ROW_NUMBER() OVER (ORDER BY ident), StringValue FROM
*
*
* Modifications
*
*
********************************************************************************************************/
RETURN (
SELECT Ident, StringValue FROM
(
SELECT Num as Ident,
CASE
WHEN DATALENGTH(@delimiter) = 0 or @delimiter IS NULL
THEN LTRIM(SUBSTRING(@string, num, 1)) --replace this line with '' if you prefer it to return nothing when no delimiter is supplied. Remove LTRIM if you want to return spaces when no delimiter is supplied
ELSE
LTRIM(RTRIM(SUBSTRING(@String,
CASE
WHEN (Num = 1 AND SUBSTRING(@String,num ,DATALENGTH(@delimiter)) <> @delimiter) THEN 1
ELSE Num + DATALENGTH(@delimiter)
END,
CASE CHARINDEX(@Delimiter, @String, Num + DATALENGTH(@delimiter))
WHEN 0 THEN LEN(@String) - Num + DATALENGTH(@delimiter)
ELSE CHARINDEX(@Delimiter, @String, Num + DATALENGTH(@delimiter)) - Num -
CASE
WHEN Num > 1 OR (Num = 1 AND SUBSTRING(@String,num ,DATALENGTH(@delimiter)) = @delimiter)
THEN DATALENGTH(@delimiter)
ELSE 0
END
END
)))
End AS StringValue
FROM dbo.Numbers
WHERE Num <= LEN(@String)
AND (
SUBSTRING(@String, Num, DATALENGTH(ISNULL(@delimiter,''))) = @Delimiter
OR Num = 1
OR DATALENGTH(ISNULL(@delimiter,'')) = 0
)
) R WHERE StringValue <> ''
)
あなたはこのようにそれを使用します。
SELECT id, pk_det, V.StringValue as userid
FROM myTable T
OUTER APPLY dbo.ParseString(T.userId) V
UDFは、次のスキーマを想定している「タリー」または番号テーブルが必要です。
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Numbers')
BEGIN
CREATE TABLE dbo.Numbers
(
Num INT NOT NULL
CONSTRAINT [PKC__Numbers__Num] PRIMARY KEY CLUSTERED (Num) on [PRIMARY]
)
;WITH Nbrs_3(n) AS (SELECT 1 UNION SELECT 0),
Nbrs_2(n) AS (SELECT 1 FROM Nbrs_3 n1 CROSS JOIN Nbrs_3 n2),
Nbrs_1(n) AS (SELECT 1 FROM Nbrs_2 n1 CROSS JOIN Nbrs_2 n2),
Nbrs_0(n) AS (SELECT 1 FROM Nbrs_1 n1 CROSS JOIN Nbrs_1 n2),
Nbrs (n) AS (SELECT 1 FROM Nbrs_0 n1 CROSS JOIN Nbrs_0 n2)
INSERT INTO dbo.Numbers(Num)
SELECT n
FROM (SELECT ROW_NUMBER() OVER (ORDER BY n)
FROM Nbrs) D (n)
WHERE n <= 50000 ;
END
数値表は、ツールセットに非常に役立ちます。 Adam Machanicを引用するには:
数値表は本当に貴重です。私は多くのデータを持つテーブル のテーブルに、カーソルのロジックを排除して、多くの他の多くの タスクをシミュレートするために、それらを使わずに非常に難しい作業をすべて 文字列操作に使用します。
私はいくつかの人々が主張したように、数字のテーブルを使っていますか? いいえ、私は効率的に数字のすべてを行う別の方法を表示 テーブルができます。それはスペースを無駄にしますか?いいえ。以下のスクリプトでは、各データベースに約012 KBのディスク容量を使用しています( )。それは絶対に です。数百万回、おそらく数十億回という結果に終わります。 ディスクスペースの投資は、開発の容易さと時間の面では を保存しました。標準SPROCに代わるものとして
http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/you-require-a-numbers-table.aspx
SQLの何味? SQLサーバー? MySQL? – MPelletier
申し訳ありませんが、MS SQL Server – Josh
の可能な複製[SQL Server 2005を使用してカンマ区切りの値を別々の行に展開するにはどうすればよいですか?](http://stackoverflow.com/questions/702968/how-do-i-expand-comma- SQL Server 2005を使用して別個の行に区切られた値) – MPelletier