본문 바로가기

SQL Server/SQL Server Tip & Tech

XML을 사용하여 문자열 Split 하기

문자열을 특정 구분자를 기준으로 split하는 방법에는 여러가지가 있습니다.

제가 최근까지 사용하던 방법은 순번(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사용)가 나았는데... 좀 더 확인해 봐야겠습니다. ^^