SQL에서 Split 함수 구현은 쉽게 찾을 수 있다. 그런데 프로젝트 진행 중, 내가 필요한 것은 더블 스플릿이다.
(더블 스필릿이라는 공식 명칭은 없다. 그냥 내 맘대로 붙여 먹은 이름이니 어디가서 들먹이면 안됨!)
즉 하나의 구분자로 문자들을 분리하고, 분리된 문자에는 또 다시 구분자가 있어 다시 스필릿 해야 하는 구조.
대략 다음과 같이...
: key1=value1,key2=value2,key3=value3
위 예시에서 첫번째 구분자는 콤마(,)이고 두번째 구분자는 이꼴(=)이다.
이 값을 차례대로 분리해서 테이블 형태로 반환하고 싶은 것이다.
과거 훌륭한 DBA로 부터 수급한 싱클 스플릿 함수 구현체에, 꾸역꾸역 더블 스플릿이 가능하도록 끼워넣었다.
사소하게 기뿌다 ^^;
ALTER FUNCTION [dbo].[UFN_DoubleSplit] (@STRMORE AS VARCHAR(8000),@STRDELIMETER1 AS VARCHAR(10),@STRDELIMETER2 AS VARCHAR(10))
RETURNS @RETURN_TABLE TABLE
(
idx int identity(1,1)
, strVALUE1 VARCHAR(500)
, strVALUE2 VARCHAR(500)
)
AS
BEGIN
DECLARE
@NINDEX INT
, @NINDEX2 INT
, @DEL_LENGTH INT
, @SUBSET VARCHAR(100)
, @STRVALUE1 VARCHAR(100)
, @STRVALUE2 VARCHAR(100)
SET @DEL_LENGTH = LEN(@STRDELIMETER1)
WHILE LEN(@STRMORE) > 0
BEGIN
SET @NINDEX = CHARINDEX(@STRDELIMETER1, @STRMORE)
IF (@NINDEX = 0)
BEGIN
SET @NINDEX2 = CHARINDEX(@STRDELIMETER2, @STRMORE)
SET @STRVALUE1 = SUBSTRING(@STRMORE, 0, @NINDEX2)
SET @STRVALUE2 = SUBSTRING(@STRMORE, @NINDEX2 + 1, LEN(@STRMORE))
INSERT @RETURN_TABLE (strVALUE1,strVALUE2) VALUES (@STRVALUE1,@STRVALUE2)
RETURN
END
ELSE IF (@NINDEX = 1)
BEGIN
SET @STRMORE = SUBSTRING(@STRMORE, @DEL_LENGTH + 1, LEN(@STRMORE))
CONTINUE
END
SET @SUBSET = SUBSTRING(@STRMORE, 0, @NINDEX)
SET @NINDEX2 = CHARINDEX(@STRDELIMETER2, @SUBSET)
SET @STRVALUE1 = SUBSTRING(@SUBSET, 0, @NINDEX2)
SET @STRVALUE2 = SUBSTRING(@SUBSET, @NINDEX2 + 1, LEN(@SUBSET))
INSERT @RETURN_TABLE (strVALUE1,strVALUE2) VALUES (@STRVALUE1,@STRVALUE2)
SET @STRMORE = SUBSTRING(@STRMORE, @NINDEX + @DEL_LENGTH, LEN(@STRMORE) - @NINDEX)
END
RETURN
END
2014.02.21 업데이트>>
이 글을 작성하고 난 뒤 'Double Split'를 프로젝트에 적용해서 잘 사용하던 중, Split 해야 할 또 하나의 값이 추가되어 버렸다.
즉, Double Split 기준의 매개변수인 'key1=value1,key2=value2,key3=value3' 형태가 다음처럼 바뀌었다.
: key1=value1&value11,key2=value2&value22,key3=value3&value33
그렇다면, Triple Split를 다시 구현할 것인가???
이런.. 유연성이 전혀 없잖어. 또 다른 기준 값이 추가되면 역시 힘겹게 수정해야 한다. 사실 이 글에서 제시한 Split 구현이 그리 깔끔하거나 쉽게 확장가능한 코드가 아니다.
결국 XML형태로 매개변수를 입력 받고 파싱해서 테이블로 반환하기로 했다. 구현이 훨씬 깔끔해져 나중에 수정을 하려고 해도 쉽게 가능해 진다.
Double Split 이여 안녕~~
RETURNS @RETURN_TABLE TABLE
(
idx int identity(1,1)
, strValue1 VARCHAR(500)
, strValue2 NVARCHAR(100)
, intValue BIGINT
)
AS
BEGIN
declare @xml xml = cast(@XMLString as xml)
INSERT @RETURN_TABLE (strValue1,strValue2,intValue)
select
x.value('data(@strValue1[1])', 'VARCHAR(500)')
, x.value('data(@strValue2[1])', 'NVARCHAR(100)')
, x.value('data((text())[1])', 'BIGINT')
from
@xml.nodes('/s') x(x)
RETURN
END
그리고 이렇게 활용하면 된다.
SELECT * FROM dbo.[UFN_ConvertFromXmlToTable]('<s strValue1="1" strValue2="11">1000</s><s strValue1="2" strValue2="22">2000</s><s strValue1="3" strValue2="33">3000</s>')
'.NET Framework' 카테고리의 다른 글
ASP.NET SignalR (0) | 2013.12.06 |
---|---|
maxConcurrentSessions in WCF (0) | 2013.11.21 |
Optimizing IIS Performance (2) | 2013.11.07 |
클라이언트의 동시 연결 수(maxconnection) (0) | 2013.11.06 |
비동기 프로그래밍에서의 메모리 누수 (0) | 2013.11.06 |