MariaDB / 함수 / LENGTH, BIT_LENGTH, CHAR_LENGTH / 문자열 길이 출력하는 함수
MariaDB에서 문자열의 바이트 수는 일반 모드의 LENGTH(), 비트 수는 BIT_LENGTH(), 문자 수는 CHAR_LENGTH()로 구합니다. 같은 문자열도 문자 인코딩 때문에 바이트 수와 문자 수가 다를 수 있으며, 1바이트는 8비트입니다. 화면에 보이는 글자 묶음의 개수와 데이터베이스가 세는 문자 수도 항상 같지는 않습니다.
세 함수가 세는 단위
| 함수 | 단위 | 주로 확인할 것 |
|---|---|---|
| LENGTH(문자열) | 일반 모드에서 바이트 | 인코딩된 문자열의 데이터 길이 |
| BIT_LENGTH(문자열) | 비트 | 바이트 길이 × 8 |
| CHAR_LENGTH(문자열) | 문자 | 문자 기준 제한이나 부분 문자열 처리 |
LENGTH()는 Oracle 호환 모드에서는 문자 수를 세는 차이가 있습니다. 모드와 관계없이 바이트 수를 명확히 나타내려면 OCTET_LENGTH()를 검토할 수 있습니다. CHAR_LENGTH()는 CHARACTER_LENGTH()라는 같은 의미의 이름도 지원합니다. BIT_LENGTH()는 문자열의 비트 길이를 반환합니다.
UTF-8 한글·ASCII를 함께 측정
다음은 테이블 없이 MariaDB 접속에서 실행합니다. SQL 원고·클라이언트는 UTF-8 입력이 정상 전달되는 상태여야 합니다. 문자열의 문자셋을 utf8mb4로 명시하고, 예제의 LENGTH 결과는 Oracle 모드가 아닌 일반 모드를 기준으로 설명합니다.
SELECT LENGTH(_utf8mb4'A1#가') AS byte_length,
BIT_LENGTH(_utf8mb4'A1#가') AS bit_length,
CHAR_LENGTH(_utf8mb4'A1#가') AS character_count,
OCTET_LENGTH(_utf8mb4'A1#가') AS explicit_bytes;
결과는 6·48·4·6입니다. 이 UTF-8 문자열에서 ASCII인 A·1·#은 각 1바이트이고 완성형 한글 가는 3바이트이므로 총 6바이트입니다. 문자 수는 네 개입니다. “특수문자는 모두 1바이트” 또는 “어떤 인코딩에서도 한글은 3바이트”라고 일반화하지 마세요. 실제 문자·인코딩에 따라 데이터 길이가 달라집니다.
SELECT CHARSET(_utf8mb4'A1#가') AS sample_charset,
HEX(_utf8mb4'A1#가') AS sample_bytes,
@@session.character_set_connection AS connection_charset,
@@session.sql_mode AS current_sql_mode;
sample_charset은 utf8mb4, sample_bytes는 413123EAB080입니다. 뒤 두 값은 현재 접속 환경에 따라 달라집니다. 예제와 값이 다르면 클라이언트의 입력 문자셋과 실제 저장 열의 문자셋, Oracle 모드 여부를 먼저 확인하세요. LENGTH는 인덱스·행 헤더·문자열 길이 접두부·페이지 여유 공간까지 합친 실제 디스크 사용량을 뜻하지 않습니다.
빈 문자열·NULL·앞뒤 공백
SELECT LENGTH('') AS empty_bytes,
BIT_LENGTH('') AS empty_bits,
CHAR_LENGTH('') AS empty_chars,
LENGTH(NULL) AS null_bytes,
BIT_LENGTH(NULL) AS null_bits,
CHAR_LENGTH(NULL) AS null_chars;
SELECT CHAR_LENGTH(' a ') AS with_spaces,
CHAR_LENGTH(TRIM(' a ')) AS after_trim;
일반 모드에서 첫 세 결과는 0·0·0, 뒤 세 값은 NULL입니다. 값이 없다는 NULL을 길이 0과 같다고 보려면 별도의 업무 규칙이 필요합니다. 공백을 포함한 a는 세 문자이고 TRIM 뒤에는 한 문자입니다. 길이 함수가 공백을 자동 제거하는 것은 아니며, 길이를 맞추려고 의미 있는 공백을 임의로 정리해서도 안 됩니다.
화면의 한 글자와 문자 수가 다른 경우
유니코드에서는 여러 코드 포인트가 하나의 사용자 인식 문자 묶음으로 표시될 수 있습니다. 유니코드 텍스트 분할 규칙 UAX #29는 이러한 글자 묶음(grapheme cluster)의 경계를 설명합니다. CHAR_LENGTH를 사용자 화면의 글자 수 제한과 항상 같은 것으로 생각하지 않는 이유입니다.
SELECT sample_no, HEX(value_text) AS bytes_hex,
OCTET_LENGTH(value_text) AS bytes_count,
BIT_LENGTH(value_text) AS bits_count,
CHAR_LENGTH(value_text) AS characters_count
FROM (
SELECT 1 AS sample_no, CONVERT(0xEAB080 USING utf8mb4) AS value_text
UNION ALL
SELECT 2, CONVERT(0xE18480E185A1 USING utf8mb4)
UNION ALL
SELECT 3, CONVERT(0xF09F9880 USING utf8mb4)
UNION ALL
SELECT 4, CONVERT(0xF09F91A9E2808DF09F92BB USING utf8mb4)
) AS unicode_samples ORDER BY sample_no;
첫 행은 완성형 가로 3바이트·24비트·1문자이고, 둘째는 한글 자모를 조합한 표현으로 6바이트·48비트·2문자입니다. 글꼴과 표시 환경에서 비슷한 가로 보일 수 있지만 내부 표현은 다릅니다. 셋째는 단일 이모지로 4바이트·32비트·1문자, 넷째는 결합자까지 포함한 이모지 표현으로 11바이트·88비트·3문자입니다. 넷째도 환경에 따라 하나의 이모지처럼 보일 수 있습니다.
길이 함수는 정규화나 사용자 인식 문자 분할을 대신하지 않습니다. 이름·닉네임 등에서 화면 글자 수가 중요한 요구라면 애플리케이션의 유니코드 처리 규칙과 데이터베이스 검증이 일치하도록 설계합니다. 임의로 바이트 중간을 잘라 UTF-8 문자를 손상시키지 않도록 문자열 자르기와 길이 측정의 단위도 맞춥니다.
열 값의 길이를 검사하는 전체 예제
아래는 실습용 learning 데이터베이스에서 CREATE·INSERT·SELECT 권한으로 실행합니다. string_length_demo가 이미 있으면 다른 실습 이름을 사용합니다. NULL·빈 문자열·한글을 포함해 문자열 값 자체를 검사하고 원본은 수정하지 않습니다.
USE learning;
CREATE TABLE string_length_demo (
id INT PRIMARY KEY,
label VARCHAR(100) CHARACTER SET utf8mb4 NULL
);
INSERT INTO string_length_demo VALUES
(1, 'abc'), (2, '가나다'), (3, ''), (4, NULL), (5, ' ab ');
SELECT id, CHAR_LENGTH(label) AS chars,
OCTET_LENGTH(label) AS bytes
FROM string_length_demo ORDER BY id;
SELECT id, label
FROM string_length_demo
WHERE CHAR_LENGTH(label) >= 3
ORDER BY id;
첫 조회의 문자 수·바이트 수는 id 순서대로 (3,3), (3,9), (0,0), (NULL,NULL), (4,4)입니다. 둘째 조회에는 id=1·2·5가 나옵니다. NULL 행은 비교 결과가 참이 아니어서 제외되므로 누락 값을 찾으려면 IS NULL 조건을 따로 사용합니다. 문자 수 조건과 바이트 수 조건 중 어느 것을 적용할지는 화면 입력 제한인지 바이트 기반 외부 형식 제한인지에 따라 정합니다.
SQL에서 숫자를 넘기면 문자열로 변환된 표현을 측정할 수 있지만, 원래 형식의 선행 0이나 표시 구분자가 보존되는 것은 아닙니다. 문자열 길이를 확인하려는 데이터는 실제 저장 타입과 표현을 확인하세요. 또한 VARCHAR의 문자 길이와 전체 행·인덱스의 바이트 제약은 별개이므로, 길이 함수 결과 하나만으로 저장·인덱싱 가능 여부를 모두 판단하지 않습니다.




