MariaDB / 함수 / INSERT / 일정 구간 문자열 교체하는 함수

MariaDB의 INSERT(str, pos, len, newstr) 함수는 문자열의 pos번째 문자부터 len개를 newstr로 바꾼 결과를 반환합니다. 위치는 1부터 시작하며, len=0이면 해당 위치 앞에 새 문자열을 끼워 넣습니다. 행을 추가하는 INSERT INTO 문과 이름이 비슷하지만 서로 다른 기능입니다.

인수와 기본 교체 결과

INSERT 문자열 함수 문서에서 str은 원본, pos는 교체 시작 위치, len은 원본에서 제거할 길이, newstr은 넣을 문자열입니다. 넣는 길이는 제거하는 길이와 달라도 됩니다. 다음은 MariaDB에 SQL을 실행할 수 있는 접속만 있으면 테이블 없이 확인할 수 있습니다.

SELECT INSERT('1234567', 4, 2, 'ABC') AS replaced,
       INSERT('1234567', 4, 0, 'ABC') AS inserted,
       INSERT('1234567', 4, 2, '') AS removed;

결과는 차례대로 123ABC67, 123ABC4567, 12367입니다. 첫 식은 네 번째 위치의 4와 다음 5를 제거한 자리에 ABC를 넣습니다. 둘째는 원본 문자를 지우지 않고 4 앞에 넣으며, 셋째는 빈 문자열로 바꿔 해당 구간만 제거합니다. SELECT에서 함수를 사용한 것만으로 저장된 원본 값이 수정되지는 않습니다.

범위를 벗어난 위치·긴 길이·NULL

SELECT INSERT('abc', 0, 1, 'X') AS zero_position,
       INSERT('abc', -1, 1, 'X') AS negative_position,
       INSERT('abc', 4, 0, 'X') AS after_end,
       INSERT('abcdef', 3, 99, 'X') AS past_remaining,
       INSERT('abc', 2, 1, NULL) AS null_replacement;

처음 세 값은 모두 abc입니다. pos가 원본 문자열 안에 없으면 원본을 그대로 반환하므로 위치 오류를 자동으로 감지해 주지는 않습니다. abc의 끝에 X를 붙이려면 다음과 같이 CONCAT 연결 함수를 사용합니다.

SELECT CONCAT('abc', 'X') AS appended;

past_remaining은 abX입니다. 시작 위치가 유효하지만 제거 길이가 남은 구간보다 길면 시작 위치부터 끝까지 바꿉니다. null_replacement는 NULL이며, 다른 인수도 NULL이면 결과가 NULL입니다. 길이는 제거할 문자 수라는 의미에 맞게 0 이상의 값으로 정하고, 데이터에서 계산한 위치가 유효한지 먼저 확인하세요.

한글 문자열과 열 값에 적용

일반 utf8mb4 문자열에서는 바이트 수 대신 문자 위치와 개수를 기준으로 다룹니다. 다음 예제는 가·나·다·라의 두 번째 문자부터 두 글자를 X로 바꾸므로 가X라가 됩니다.

SELECT INSERT(_utf8mb4'가나다라', 2, 2, 'X') AS korean_result;

문자열을 바이너리로 변환하거나 서로 다른 문자 인코딩의 데이터를 혼합한 경우에는 같은 전제를 그대로 적용하지 않습니다. 눈에 한 글자로 보이는 조합 문자·이모지도 내부 문자 수가 다를 수 있으므로 사용자 화면의 글자 단위 편집까지 이 함수가 모두 대신하는 것은 아닙니다.

아래는 합성 주문 코드를 표시할 때 마지막 여섯 자리를 가리는 예입니다. 실습용 learning 데이터베이스에서 CREATE·INSERT·SELECT 권한으로 실행하고, string_insert_demo가 이미 있으면 다른 이름을 사용합니다. 규격이 맞지 않는 코드는 부분 노출 대신 별도 안내로 표시합니다.

USE learning;
CREATE TABLE string_insert_demo (
    id INT PRIMARY KEY,
    order_code VARCHAR(40) NULL
) DEFAULT CHARSET=utf8mb4;
INSERT INTO string_insert_demo VALUES
    (1, 'ORD-2026-000123'), (2, 'SHORT'), (3, NULL);

SELECT id,
       CASE
           WHEN order_code REGEXP '^ORD-[0-9]{4}-[0-9]{6}$'
           THEN INSERT(order_code, 10, 6, '******')
           ELSE '[형식 확인 필요]'
       END AS display_code
FROM string_insert_demo ORDER BY id;

id=1은 ORD-2026-******, 나머지 두 행은 [형식 확인 필요]입니다. 이는 표시용 변환이며 원본 열에는 합성 코드가 그대로 남습니다. 민감정보에 같은 패턴을 적용해도 데이터 암호화나 익명화가 되는 것은 아닙니다. 원본 조회 권한·로그·다른 응답 경로에서 노출되지 않는지의 검토는 별개입니다.

값을 찾아 바꾸는 REPLACE와 선택 기준

시작 위치와 제거 길이를 알고 있으면 INSERT()가 맞고, 특정 문자열이 나타나는 곳을 찾아 전부 바꾸려면 REPLACE()를 사용합니다. 다음은 같은 원본에서 두 동작을 비교합니다.

SELECT INSERT('A-B-A', 1, 1, 'X') AS positional,
       REPLACE('A-B-A', 'A', 'X') AS by_value;

positional은 X-B-A, by_value는 X-B-X입니다. INSERT()는 지정된 구간 한 곳만 다루고, REPLACE()는 찾은 값을 기준으로 여러 곳을 치환할 수 있습니다. 데이터를 실제로 수정하려면 UPDATE의 SET에서 이 표현식을 사용해야 하지만, 먼저 SELECT로 대상·변환 결과를 검토하고 WHERE와 트랜잭션·백업 계획을 따로 마련합니다. 이 글의 SELECT 예제를 실행한 것만으로 원본이 바뀌지는 않습니다.