이 글은 새로운 블로그로 옮겼습니다. 5초후 자동으로 이동합니다.
▶ 새로운 블로그 주소: https://prodskill.com/
▶ 새로운 글 주소: https://prodskill.com/sybase-ase-utf8-byte-char-length/
Non-Unicode 인코딩인 EUC-KSC에서 Unicode 인코딩인 UTF-8로 변환하는 프로젝트에서 만들어서 사용했던 함수이다. EUC-KSC에서 varchar(10)으로 선언된 컬럼을 UTF-8로 변환시 최대 바이트 수를 확인할 필요가 있는데, 기본으로 제공하는 함수가 없어서 직접 만들어서 사용했다.
DBMS는 Sybase ASE v15.5 이다. MS-SQL과 유사성이 높으므로 MS-SQL에서도 별다른 수정없이 동작할 것이라고 생각한다.
▼ 함수 소스 코드
IF OBJECT_ID('dbo.GET_UTF8_BYTE') IS NOT NULL
DROP FUNCTION dbo.GET_UTF8_BYTE
GO
CREATE FUNCTION dbo.GET_UTF8_BYTE
(
@IN_VAL VARCHAR(4000)
)
RETURNS INT
AS
BEGIN
DECLARE @CHK_LENGTH INT, @I INT, @CHK_BYTE INT, @BYTE_LEN INT, @UTF8_BYTE_LEN INT, @SUM_UTF8_BYTE_LEN INT
SELECT @I = 1, @CHK_LENGTH = LEN(@IN_VAL), @SUM_UTF8_BYTE_LEN = 0
WHILE @I <= @CHK_LENGTH
BEGIN
SELECT @CHK_BYTE = ASCII(SUBSTRING(@IN_VAL, @I, 1))
IF @CHK_BYTE >= 128 -- ASCII 코드가 alpha, numeric, control 문자 범위를 넘는 경우(2 Byte 문자일 경우)
SELECT @BYTE_LEN = 2, @UTF8_BYTE_LEN = 3
ELSE
SELECT @BYTE_LEN = 1, @UTF8_BYTE_LEN = 1
SELECT @SUM_UTF8_BYTE_LEN = @SUM_UTF8_BYTE_LEN + @UTF8_BYTE_LEN, @I = @I + @BYTE_LEN
END
RETURN @SUM_UTF8_BYTE_LEN
END
GO
이 코드는 다음과 같은 사실에 기반하여 작성하였다.
- Non-Unicode 1 Byte의 ASCII 코드가 128 이상이면 2바이트 문자(한,중,일 등)
- Non-Unicode 한글 1글자(2바이트)는 UTF-8 인코딩에서 3바이트로 저장됨
주요 코드에 대한 설명은 다음과 같다.
- 18행: 입력 문자열을 한 바이트씩 읽는다.
- 21행: 읽은 바이트의 ASCII 코드가 128 이상인 경우 건너뛸 바이트 길이를 2로 설정, UTF-8 바이트 수를 3 증가
- 23행: 읽은 바이트의 ASCII 코드가 128 미만인 경우 건너뛸 바이트 길이를 1로 설정, UTF-8 바이트 수를 1 증가
- 25행: UTF-8 바이트 수 합계 누적, WHILE 반복문의 조건 변수 @I 값을 건너뛸 바이트 길이 만큼 증가
이 함수를 다음과 같이 변형하면 UTF-8 바이트 수가 아닌 글자수를 얻을 수 있다.
IF OBJECT_ID('dbo.GET_CHAR_CNT') IS NOT NULL
DROP FUNCTION dbo.GET_CHAR_CNT
GO
CREATE FUNCTION dbo.GET_CHAR_CNT
(
@IN_VAL VARCHAR(4000)
)
RETURNS INT
AS
BEGIN
DECLARE @CHK_LENGTH INT, @I INT, @CHK_BYTE INT, @BYTE_LEN INT, @UTF8_BYTE_LEN INT, @SUM_UTF8_BYTE_LEN INT, @SUM_CHAR_CNT INT
SELECT @I = 1, @CHK_LENGTH = LEN(@IN_VAL), @SUM_UTF8_BYTE_LEN = 0, @SUM_CHAR_CNT = 0
WHILE @I <= @CHK_LENGTH
BEGIN
SELECT @CHK_BYTE = ASCII(SUBSTRING(@IN_VAL, @I, 1))
IF @CHK_BYTE >= 128 -- ASCII 코드가 alpha, numeric, control 문자 범위를 넘는 경우(2 Byte 문자일 경우)
SELECT @BYTE_LEN = 2, @UTF8_BYTE_LEN = 3
ELSE
SELECT @BYTE_LEN = 1, @UTF8_BYTE_LEN = 1
SELECT @SUM_UTF8_BYTE_LEN = @SUM_UTF8_BYTE_LEN + @UTF8_BYTE_LEN, @I = @I + @BYTE_LEN
SELECT @SUM_CHAR_CNT = @SUM_CHAR_CNT + 1
END
--RETURN @SUM_UTF8_BYTE_LEN
RETURN @SUM_CHAR_CNT
END
16행부터 시작하는 WHILE 반복문은 @I 변수를 조건으로 종료한다. @BYTE_LEN 변수는 읽은 바이트의 ASCII 코드에 따라 2(2 바이트 문자) 또는 1(1 바이트 문자)로 설정되고 25행에서 @I에 더해진다. 이 로직으로 WHILE 반복문은 문자개수만큼 반복 실행된다.
26행에서 @SUM_CHAR_CNT는 1씩 증가시키는 이유는 반복횟수가 문자개수이기 때문이다.
댓글