제가 최근까지 사용하던 방법은 순번(sequential number)이 들어있는 테이블을 이용한 방법이었습니다.
그래서 제가 디자인한 데이터베이스에는 항상 Tally라는 테이블과 IF_Split이라는 인라인함수가 들어있죠.
SELECT TOP 10000 IDENTITY(int, 1, 1) AS n
INTO dbo.Tally
FROM master.dbo.syscolumns A
CROSS JOIN master.dbo.syscolumns B
GO
ALTER TABLE dbo.Tally ADD CONSTRAINT PK_Tally PRIMARY KEY CLUSTERED (n)
GO
CREATE FUNCTION dbo.IF_Split (
@nvcString nvarchar(max),
@nvcDelimiter nvarchar(1)
)
RETURNS TABLE
AS
RETURN (
SELECT SUBSTRING(@nvcDelimiter + @nvcString + @nvcDelimiter, n + 1, CHARINDEX(@nvcDelimiter, @nvcDelimiter + @nvcString + @nvcDelimiter, n + 1) - n - 1) AS string
FROM dbo.Tally WITH (NOLOCK)
WHERE n < (DATALENGTH(@nvcDelimiter + @nvcString + @nvcDelimiter) / 2) AND SUBSTRING(@nvcDelimiter + @nvcString + @nvcDelimiter, n, 1) = @nvcDelimiter
)
나름 성능도 괜찮고 SP 작성할 때 요긴합니다.
음... 그런데 xml을 사용한 이런 방법도 있더구요.
(출처 : http://www.sqlservercentral.com/articles/XML/66932/)
xml 타입으로 변경해야하기 때문에 인라인 함수 대신 테이블 함수로 만들었습니다.
CREATE FUNCTION dbo.TF_Split (
@nvcString nvarchar(max),
@nvcDelimiter nvarchar(1)
)
RETURNS @tblResult table (string nvarchar(4000) NOT NULL)
AS
BEGIN
DECLARE @xmlString xml;
SET @xmlString = CAST(N'<X>'+REPLACE(@nvcString, @nvcDelimiter, N'</X><X>')+N'</X>' AS xml);
INSERT @tblResult (string)
SELECT N.value(N'.', 'nvarchar(4000)') FROM @xmlString.nodes(N'X') AS T(N)
RETURN;
END
CROSS APPLY를 사용하면 이런 응용도 가능합니다. (물론 IF_Split으로도 가능합니다.)
참고로... 2개 이상의 구분자를 사용하는 경우에는 이런 식으로도 쓸 수 있습니다.
두 가지 방식 모두... 용법에 관련해서는 거의 차이가 없습니다.
중요한 건 어느쪽의 성능이 우수한가... 겠죠.
간단한 테스트에서는 후자 (xml사용)가 나았는데... 좀 더 확인해 봐야겠습니다. ^^
'SQL Server > SQL Server Tip & Tech' 카테고리의 다른 글
SQL Server 2005 암호화 (0) | 2009.07.15 |
---|---|
INSERT 스크립트 생성하기 (0) | 2009.07.14 |
Change Tracking [SQL Server 2008] (0) | 2009.06.24 |
테이블 변수 vs 임시 테이블 (0) | 2009.06.11 |
Vardecimal Storage Format을 사용하여 데이터베이스 사이즈 줄이기 (0) | 2009.06.01 |