AD JB Toolbox 01

MariaDB 강좌 / 문자열 다루기: 연결·추출·치환·길이

문자열 함수는 글자를 연결·추출·치환하거나 길이를 계산해 조회 결과를 가공합니다. CONCAT·SUBSTRING·REPLACE·CHAR_LENGTH를 목적에 맞게 선택하되, NULL 처리와 문자 수·바이트 수를 구분해야 원본 의미를 훼손하지 않습니다.

연결·추출·치환의 역할 나누기

상품명과 분류를 한 줄로 보여 주는 일, 코드의 일부를 꺼내는 일, 전화번호 구분자를 제거하는 일은 서로 다른 작업입니다. 문자열 함수를 SELECT에 사용하면 출력값이 계산될 뿐 저장된 상품명이 자동으로 수정되지는 않습니다. 먼저 무엇을 원본으로 보관하고 무엇을 화면 표시로 만들지 정하세요. 함수 입력이 담기는 열의 저장 조건은 문자열 타입 선택하기: CHAR·VARCHAR·TEXT, 누락값의 의미를 보존하는 기준은 NULL을 올바르게 비교하기: IS NULL·COALESCE과 함께 확인하세요.

함수 용도 중요한 기준
CONCAT 문자열 이어 붙이기 일반 모드에서 인수에 NULL이 있으면 결과 NULL
CONCAT_WS 구분자로 연결 NULL 인수는 건너뛰지만 빈 문자열은 유지
SUBSTRING 위치와 길이로 추출 첫 문자 위치는 1
REPLACE 일치하는 부분 문자열 치환 행을 대체하는 REPLACE 문과 별개
CHAR_LENGTH / LENGTH 문자 수 / 바이트 수 멀티바이트 문자에서 서로 다름

연습 데이터를 준비하고 표시용 문자열 만들기

학습용 MariaDB 서버의 shopcourse에 course_user로 접속합니다. 명령줄 클라이언트와 UTF-8 SQL 파일 실행 방법대로 코드를 UTF-8 파일에 저장하고 SOURCE C:/mariadb-lab/lesson.sql;처럼 실제 파일 경로로 실행할 수 있습니다. SQL 문은 운영체제 터미널이 아닌 MariaDB 연결 안에서 실행합니다.

먼저 SELECT VERSION(), DATABASE();와 SHOW TABLES;로 대상 서버·DB·이름 중복을 확인합니다. 아래 products_19_lab는 이 글의 독립된 연습용 이름입니다. 이미 존재하면 정의와 행을 확인하고, 보관할 자료가 없는 이 글의 실습 테이블임이 확실할 때만 마지막 절의 정리 순서로 지운 뒤 다시 만듭니다. 기존 강좌의 동명 없는 테이블이나 운영 데이터는 삭제하지 않습니다.

USE shopcourse;
CREATE TABLE products_19_lab (
  product_id INT NOT NULL AUTO_INCREMENT,
  product_name VARCHAR(100) NOT NULL,
  category VARCHAR(30) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  stock INT NOT NULL DEFAULT 0,
  note VARCHAR(100) NULL DEFAULT NULL,
  PRIMARY KEY (product_id),
  CONSTRAINT ck_p19_price CHECK (price >= 0),
  CONSTRAINT ck_p19_stock CHECK (stock >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO products_19_lab (product_id,product_name,category,price,stock,note) VALUES (1, '노트', '문구', 3500.00, 20, NULL),
  (2, '볼펜', '문구', 1500.00, 0, ''),
  (3, '머그컵', '생활', 8000.00, 12, '선물 포장'),
  (4, '스탠드', '생활', 25000.00, 5, NULL),
  (5, '파일', '문구', 1500.00, 50, ''),
  (6, '케이블', '전자', 8000.00, 0, '호환 확인');

상품 메모에는 NULL과 빈 문자열이 함께 있습니다. 같은 입력에 서로 다른 연결 함수를 적용하면 표시 정책이 드러납니다. NULL과 빈 문자열 비교 실습에서 두 상태의 차이를 먼저 확인할 수 있습니다.

SELECT product_id, CONCAT(product_name,' / ',category) AS label,
 CONCAT_WS(' / ',product_name,note) AS note_label
FROM products_19_lab ORDER BY product_id;

첫 상품의 label은 노트 / 문구이고 note_label은 노트입니다. note가 NULL인 경우 CONCAT_WS가 해당 인수를 생략했기 때문입니다. 반면 볼펜의 메모는 빈 문자열이므로 구분자가 붙은 결과가 될 수 있습니다. 화면에 구분자가 남는다고 NULL 데이터로 바꾸지 말고 빈 메모의 표시 정책을 정해야 합니다.

문자 위치를 기준으로 필요한 부분 꺼내기

SELECT SUBSTRING('MariaDB',1,5), SUBSTRING('MariaDB',-2);
SELECT REPLACE('010-1234-5678','-','') AS normalized_phone;

결과는 Maria, DB, 01012345678입니다. SUBSTRING의 시작 위치는 0이 아니라 1이며 음수 위치는 뒤쪽을 기준으로 계산합니다. 길이는 바이트가 아닌 문자 기준이므로 한글 문자열도 문자 위치로 다룰 수 있습니다. 코드 앞부분을 무조건 자르기 전에 그 위치가 업무상 고정되어 있는지도 확인하세요. SUBSTRING 문법과 위치 규칙을 참고할 수 있습니다.

REPLACE 함수는 일치하는 부분 문자열을 바꿉니다. 문서 전체를 업데이트하는 명령은 아니며, 전화번호에서 구분자를 지운 결과를 식별값으로 저장할지는 별도의 검증이 필요합니다. 국가 번호·내선·앞자리 0 같은 정보를 숫자 변환으로 없애지 않도록 주의합니다.

문자 수와 바이트 수를 비교하기

SELECT CHAR_LENGTH('한글'), LENGTH('한글'),
 CHAR_LENGTH('🙂'), LENGTH('🙂');

클라이언트와 문자열이 utf8mb4인 실습에서는 한글은 2문자·6바이트, 이모지는 1문자·4바이트입니다. UI에서 보이는 하나의 기호가 여러 코드 포인트의 조합일 수도 있으므로 CHAR_LENGTH가 언제나 사람이 인식하는 글자 묶음의 수와 같다고 단정하지는 않습니다.

입력 제한을 100자로 정하는 일과 네트워크·저장소의 100바이트를 제한하는 일은 다릅니다. 문자열 타입과 길이 기준을 함께 확인하고, 바이트 수를 임의로 잘라 잘못된 UTF-8 조각을 만들지 않습니다.

NULL·빈 문자열·공백 정리의 차이 확인하기

SELECT CONCAT('노트',NULL),
 CONCAT_WS(' / ','노트',NULL,'');
SELECT CONCAT('[',TRIM('  노트  '),']');

첫 결과는 NULL이며 둘째 결과에는 빈 문자열 때문에 마지막 구분자가 남습니다. TRIM 예제는 양끝의 기본 공백을 제거해 [노트]를 만듭니다. TRIM이 모든 종류의 유니코드 공백이나 문자열 중간 공백까지 제거하는 기능은 아닙니다. 사용자 이름·비밀번호처럼 공백 자체가 의미 있는 값은 일괄 정리하지 않습니다.

문자열 비교에는 열의 정렬 규칙이 영향을 줍니다. 대소문자·악센트·끝 공백을 구분해야 하는 업무에서는 함수만 바꾸기보다 타입과 collation을 함께 검토합니다. MariaDB 문자열 함수 안내에서 함수별 NULL과 변환 동작을 확인하세요.

원본과 가공 결과를 나란히 점검하고 반복하기

새 표시값만 출력하지 말고 기본키·원본 열·가공 열을 함께 조회합니다. 잘린 값이 예상보다 짧으면 위치와 길이를, 연결 결과가 NULL이면 각 인수를, 한글이 깨지면 파일·연결 문자 집합을 확인합니다. 원본을 UPDATE하기 전에는 SELECT로 가공 규칙을 검증하고 복구 가능한 변경 절차를 따르세요.

반복하기 전 현재 DB와 실제 정의·행을 확인하고 필요한 자료를 백업합니다. 보관할 데이터가 없는 이 글의 전용 실습 객체만 아래 순서로 정리합니다. 외래키가 있으면 자식부터 지웁니다. DROP TABLE은 구조와 데이터를 모두 없애며 일반적인 ROLLBACK으로 복원되지 않으므로 취소 가능한 DML 실습과 분리합니다.

DROP TABLE shopcourse.products_19_lab;
같은 카테고리의 다른 글
MariaDB 강좌 / 복제 구조와 지연·오류·장애 대응 이해하기

MariaDB 강좌 / 복제 구조와 지연·오류·장애 대응 이해하기

빈 두 서버를 준비하는 로컬 Compose 구성과 복제 상태·지연·오류 진단을 설명합니다. 적용 중지·재개를 관찰하고 백업과 장애 승격의 경계를 구분합니다.

MariaDB 강좌 / 윈도 함수로 누적 합계와 이전·다음 행 비교하기

MariaDB 강좌 / 윈도 함수로 누적 합계와 이전·다음 행 비교하기

누적 합계와 LAG·LEAD를 계산하고 동점 데이터로 ROWS·RANGE를 비교합니다. 날짜 필터를 누적 전후에 적용한 결과와 정렬·기간 경계를 확인합니다.

MariaDB 강좌 / 중복 데이터를 줄이는 정규화와 주문 데이터베이스 설계

MariaDB 강좌 / 중복 데이터를 줄이는 정규화와 주문 데이터베이스 설계

주문 상세에 반복한 고객 정보의 변경 오류를 관찰하고 키별 사실을 네 테이블로 나눕니다. 부분·이행 종속, 거래 당시 단가와 스냅샷 보존, 무결성 제약과 성능의 별도 검토를 설명합니다.

MariaDB / 데이터베이스 / 조회, 생성, 삭제, 이름 변경

MariaDB / 데이터베이스 / 조회, 생성, 삭제, 이름 변경

MariaDB에서 데이터베이스를 조회하는 방법, 생성하는 방법, 삭제하는 방법, 이름을 변경하는 방법에 대해서 알아봅니다.

MariaDB 강좌 / 숫자 계산과 타입 변환: ROUND·CAST

MariaDB 강좌 / 숫자 계산과 타입 변환: ROUND·CAST

ROUND와 CAST를 할인 금액·정확한 소수·숫자 문자열로 실습합니다. 반올림 시점, 앞자리 0 손실, 잘림 경고와 SQL 모드에 따른 저장 동작의 차이를 설명합니다.

MariaDB 강좌 / EXPLAIN으로 실행 계획 읽고 인덱스 전후 비교하기

MariaDB 강좌 / EXPLAIN으로 실행 계획 읽고 인덱스 전후 비교하기

1000행 실습으로 인덱스 전후 EXPLAIN과 실제 반환 행을 비교합니다. ANALYZE FORMAT=JSON의 실행 정보와 통계 갱신을 구분하고 결과·환경을 기록합니다.

MariaDB 강좌 / 백업을 별도 데이터베이스에 복원하고 검증하기

MariaDB 강좌 / 백업을 별도 데이터베이스에 복원하고 검증하기

새 원본과 별도 빈 DB를 준비해 덤프를 복원하고 객체·행 수·키·업무 합계를 비교합니다. 파일 안의 DB 전환·삭제 문장, 클라이언트 호환성과 부분 복원 실패의 대응을 설명합니다.

MariaDB 강좌 / UPDATE·DELETE를 실행하기 전 대상 행 확인하기

MariaDB 강좌 / UPDATE·DELETE를 실행하기 전 대상 행 확인하기

UPDATE·DELETE 전에 기본키와 현재값으로 대상 행을 확인하고, InnoDB 트랜잭션에서 수정·삭제 결과를 검증한 뒤 취소합니다. 영향받은 행 수와 ROLLBACK의 적용 한계도 설명합니다.

MariaDB 강좌 / NULL을 올바르게 비교하기: IS NULL·COALESCE

MariaDB 강좌 / NULL을 올바르게 비교하기: IS NULL·COALESCE

NULL·빈 문자열·0을 구분하고 IS NULL·IS NOT NULL과 COALESCE의 역할을 실습합니다. 일반 비교에서 빠지는 NULL 행, NULL-safe 비교와 NOT IN 목록의 함정을 설명합니다.

MariaDB 강좌 / CREATE TABLE로 테이블 구조 정의하기

MariaDB 강좌 / CREATE TABLE로 테이블 구조 정의하기

상품 테이블을 예로 열·타입·기본값·기본키·저장 엔진을 정의하고 실제 생성 결과를 확인합니다. 기존 테이블 처리, IF NOT EXISTS의 한계와 안전한 반복 실습 방법도 설명합니다.