본문 바로가기
DataBase/mssql

[MSSQL] STRING_SPLIT 입력 순서대로 자르기

by 노랑파랑 2023. 7. 7.
반응형

 

MS SQL의 STRING_SPLIT 함수는 문자열을 지정한 구분자 기준으로 나눈 결과를 반환한다. 그러나 STRING_SPLIT 함수는 결과의 출력 순서를 보장하지 않는, 즉 데이터베이스의 내부 구현 및 실행 계획에 따라 임의의 순서로 결과가 출력된다. 

서비스를 운영하다보면 다른 기능에서 받은 파라미터 순서대로 결과를 출력해야 할 때가 있다.

만약 사용하는 SQL Server 버전이 2022라면 아래와 같이 새로 추가된 옵션(enable_ordinal)으로 출력 순서를 제어할 수 있을지 모른다.

STRING_SPLIT ( string , separator [ , enable_ordinal ] )

 


SELECT * FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ', 1);

 

하지만 내가 사용하고 있는 버전은 2022버전보다 낮기때문에 다른 방식을 찾아보았다.

 

1. ROW_NUMBER 사용하기

 입력된 순서를 기억하기 위해 인덱스 또는 식별자를 포함한 결과를 만드는 방법이다.

DECLARE @str NVARCHAR(MAX) = '1,2,3,4,5,6,7,8,9,10,11,12';
DECLARE @delimiter NVARCHAR(1) = ',';

SELECT 
    value AS splitted_value,
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS idx
FROM 
    STRING_SPLIT(@str, @delimiter)
ORDER BY idx;

 

여기서 (SELECT NULL)은 정렬 조건으로 사용되는데, 실제로 정렬을 수행하지 않기 위해 사용한다. 즉 ROW_NUMBER() OVER (ORDER BY (SELECT NULL))는 정렬 조건이 필요하지 않는 순번을 할당하고자 할 때 사용되는 구문이다.

해당 구문을 이용하여 분할한 값에 대한 인덱스를 생성하고 order by절로 정렬한 것이다.

 

 

2. 테이블 변수 사용

두번째 방법은 테이블 변수를 생성하여 IDENTITY열을 추가하는 방법이다.

DECLARE @str NVARCHAR(MAX) = '1,2,3,4,5,6,7,8,9,10,11,12';
DECLARE @delimiter NVARCHAR(1) = ',';

DECLARE @resultTable TABLE
(
    ID INT IDENTITY(1, 1),
    Value NVARCHAR(100)
);

INSERT INTO @resultTable (Value)
SELECT value
FROM STRING_SPLIT(@str, @delimiter);

SELECT *
FROM @resultTable
ORDER BY ID;

 

IDENTITY 열과 값을 저장할 열을 포함한 테이블 변수를 생성하고, STRING_SPLIT 함수의 결과를 @resultTable에 저장한다.

이로 인해 STRING_SPLIT 함수의 결과를 테이블로 저장해서, IDENTITY 열을 통해 입력된 순서를 추적할 수 있게된다.

하지만 테이블 변수는 메모리에 저장되므로 대량의 데이터를 다룰 때는 메모리 부하가 발생할 수 있으니 주의하자.

 

 

 

 

반응형