> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL 문자열 함수

> MySQL 문자열 함수 참조 가이드: CONCAT, SUBSTRING, TRIM, REPLACE, UPPER, LOWER, LENGTH, LIKE, REGEXP, FORMAT, 그리고 흔한 문자열 조작 패턴입니다.

> [card] [VillageSQL is a drop-in replacement for MySQL with extensions.](https://villagesql.com/docs/en/8.4/stable/install-server.md)
>
> All examples on this page work on VillageSQL. Install Now →

MySQL의 문자열 함수는 텍스트를 나누고, 합치고, 검색하고, 서식을 지정하고, 비교하는 작업을 다룹니다. 대부분은 같은 규칙을 따릅니다: 1부터 시작하는 인덱스, NULL 전파(인수 중 하나라도 NULL이면 NULL을 반환), 그리고 기본적으로 대소문자를 구분하지 않는 비교입니다.

## 결합과 분리

**CONCAT** — 문자열을 이어 붙입니다:

```sql theme={null}
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;

-- CONCAT_WS: join with a separator, skipping NULLs
SELECT CONCAT_WS(', ', city, state, country) AS address FROM locations;
```

`CONCAT`은 인수에 NULL이 있으면 NULL을 반환합니다. `CONCAT_WS`는 NULL 값을 건너뛰지만, NULL이 아닌 값 사이의 구분자는 유지합니다.

**SUBSTRING / SUBSTR / MID** — 문자열의 일부를 추출합니다:

```sql theme={null}
-- SUBSTRING(string, start, length)  — 1-based indexing
SELECT SUBSTRING('Hello, World!', 1, 5);   -- 'Hello'
SELECT SUBSTRING('Hello, World!', 8);      -- 'World!'  (to end of string)
SELECT SUBSTRING('Hello, World!', -6);     -- 'World!'  (from the right)
```

**SUBSTRING\_INDEX** — 구분자를 기준으로 나눕니다:

```sql theme={null}
-- Get everything before the second comma
SELECT SUBSTRING_INDEX('a,b,c,d', ',', 2);   -- 'a,b'

-- Get everything after the last dot (domain from email)
SELECT SUBSTRING_INDEX('user@example.com', '@', -1);  -- 'example.com'
```

## 문자열 안에서 검색하기

**LOCATE / POSITION / INSTR** — 부분 문자열을 찾습니다:

```sql theme={null}
SELECT LOCATE('World', 'Hello, World!');       -- 8  (1-based position)
SELECT LOCATE('world', 'Hello, World!');       -- 8  (case-insensitive by default)
SELECT LOCATE('xyz', 'Hello, World!');         -- 0  (not found)

-- LOCATE with start position
SELECT LOCATE('o', 'Hello, World!', 6);        -- 9  (skips first 'o')
```

**LIKE** — 와일드카드를 사용한 패턴 일치:

```sql theme={null}
-- % matches zero or more characters, _ matches exactly one
SELECT * FROM products WHERE name LIKE 'Widget%';       -- starts with Widget
SELECT * FROM products WHERE name LIKE '%Pro%';         -- contains Pro
SELECT * FROM products WHERE code LIKE 'SKU-___-2024';  -- three chars in middle
```

**REGEXP / RLIKE** — 정규 표현식 일치:

```sql theme={null}
SELECT * FROM users WHERE email REGEXP '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$';
SELECT * FROM products WHERE name REGEXP 'Pro|Plus|Max';
```

`REGEXP`는 POSIX 정규식 구문을 사용합니다. 함수 형태가 필요하면 `REGEXP_LIKE()`(MySQL 8.0 이상)를 사용하세요.

## 문자열 수정하기

**REPLACE** — 부분 문자열의 모든 출현을 바꿉니다:

```sql theme={null}
SELECT REPLACE('Hello, World!', 'World', 'MySQL');  -- 'Hello, MySQL!'
UPDATE articles SET content = REPLACE(content, 'old_term', 'new_term');
```

**TRIM / LTRIM / RTRIM** — 공백이나 특정 문자를 제거합니다:

```sql theme={null}
SELECT TRIM('  hello  ');                    -- 'hello'
SELECT TRIM(LEADING '0' FROM '007');         -- '7'
SELECT TRIM(BOTH 'x' FROM 'xxhelloxx');      -- 'hello'
```

**UPPER / LOWER** — 대소문자를 바꿉니다:

```sql theme={null}
SELECT UPPER('hello');   -- 'HELLO'
SELECT LOWER('HELLO');   -- 'hello'
```

**LPAD / RPAD** — 고정 길이로 채웁니다:

```sql theme={null}
SELECT LPAD('42', 6, '0');    -- '000042'
SELECT RPAD('hello', 10, '.');  -- 'hello.....'
```

**REPEAT** — 문자열을 N번 반복합니다:

```sql theme={null}
SELECT REPEAT('ab', 3);   -- 'ababab'
```

**REVERSE** — 문자열을 뒤집습니다:

```sql theme={null}
SELECT REVERSE('hello');  -- 'olleh'
```

## 길이와 비교

MySQL에는 멀티바이트 문자에 대해 다른 결과를 내는 2개의 길이 함수가 있습니다:

| 함수 | 측정하는 것 |
| :- | :- |
| `LENGTH(s)` | 바이트 길이 |
| `CHAR_LENGTH(s)` / `CHARACTER_LENGTH(s)` | 문자 길이 |

```sql theme={null}
SELECT LENGTH('café');      -- 5  (the é is 2 bytes in UTF-8)
SELECT CHAR_LENGTH('café'); -- 4  (4 characters)
```

바이트가 아니라 문자 수가 중요할 때는 항상 `CHAR_LENGTH`를 사용하세요.

**STRCMP** — 두 문자열을 비교하고 -1, 0, 또는 1을 반환합니다:

```sql theme={null}
SELECT STRCMP('abc', 'abc');   -- 0
SELECT STRCMP('abc', 'abd');   -- -1
SELECT STRCMP('abd', 'abc');   -- 1
```

## 서식 지정

**FORMAT** — 숫자에 천 단위 구분 기호를 넣어 서식을 지정합니다:

```sql theme={null}
SELECT FORMAT(1234567.891, 2);    -- '1,234,567.89'
SELECT FORMAT(1234567.891, 2, 'de_DE');  -- '1.234.567,89'  (German locale)
```

**LEFT / RIGHT** — 시작이나 끝에서 N개의 문자를 가져옵니다:

```sql theme={null}
SELECT LEFT('Hello, World!', 5);   -- 'Hello'
SELECT RIGHT('Hello, World!', 6);  -- 'World!'
```

## 흔한 패턴

이메일 주소에서 도메인 추출하기:

```sql theme={null}
SELECT SUBSTRING_INDEX(email, '@', -1) AS domain FROM users;
```

표시용으로 긴 문자열 자르기:

```sql theme={null}
SELECT CASE
    WHEN CHAR_LENGTH(description) > 100
    THEN CONCAT(LEFT(description, 97), '...')
    ELSE description
END AS short_description
FROM products;
```

공백 정규화하기:

```sql theme={null}
UPDATE users SET name = TRIM(REGEXP_REPLACE(name, '\\s+', ' '));
```

## 자주 묻는 질문

#### MySQL 문자열 비교는 대소문자를 구분하나요?

기본적으로는 구분하지 않습니다. 문자열 비교는 열의 콜레이션을 사용하며, 가장 흔한 콜레이션은 대소문자를 구분하지 않습니다(예: `utf8mb4_general_ci`, 여기서 `ci`는 case-insensitive를 뜻합니다). 대소문자를 구분하는 비교가 필요하면 `_cs` 콜레이션이나 `BINARY` 연산자를 사용하세요:

```sql theme={null}
SELECT * FROM users WHERE BINARY username = 'Alice';
-- or: WHERE username COLLATE utf8mb4_bin = 'Alice'
```

#### CHAR\_LENGTH와 LENGTH의 차이는 무엇인가요?

`LENGTH`는 바이트 수를 반환하고, `CHAR_LENGTH`는 문자 수를 반환합니다. ASCII 문자열에서는 둘이 같습니다. 멀티바이트 문자(악센트가 붙은 글자, 이모지, CJK)가 있는 UTF-8 문자열에서는 다릅니다. 사용자에게 보이는 문자열 길이 제한에는 `CHAR_LENGTH`를 사용하세요.

## 문제 해결

| 문제 | 해결 방법 |
| :- | :- |
| `CONCAT`이 NULL을 반환 | 인수 중 하나가 NULL임 — 연결하기 전에 `COALESCE(col, '')`로 NULL을 바꾸거나 `CONCAT_WS`를 사용 |
| `LIKE '%pattern%'`이 느림 | 앞쪽 와일드카드가 인덱스 사용을 막음 — 대규모 텍스트 검색에는 FULLTEXT 인덱스를 고려 |
| 문자열 비교가 예상한 행과 일치하지 않음 | 대소문자 구분 또는 콜레이션 불일치 — `SHOW CREATE TABLE`로 열의 콜레이션을 확인 |
| `REPLACE`가 `LIKE`가 일치시킨 것과 일치하지 않음 | `REPLACE`는 바이트 단위로 비교하고 연결 콜레이션을 무시하므로, `_ci` 열에서도 대소문자를 *구분*함 — `=`, `LIKE`, `LOCATE`와 다름 |
| `SUBSTRING`이 NULL이 아니라 빈 문자열을 반환 | 범위를 벗어난 위치의 SUBSTRING은 NULL이 아니라 빈 문자열을 반환함 |

## 함께 보기

* [MySQL 문자 집합과 콜레이션](https://villagesql.com/docs/ko/guides/character-sets.md) — 문자열 함수는 콜레이션에 따라 다르게 동작합니다
* [MySQL 전문 검색](https://villagesql.com/docs/ko/guides/full-text-search.md) — LIKE를 넘어선 대규모 문자열 검색
* [MySQL 열 별칭](https://villagesql.com/docs/ko/tutorial/column-aliases.md) — 문자열 표현식이 만드는 열에 이름 붙이기
* [MySQL LIKE](https://villagesql.com/docs/ko/tutorial/like.md) — 이 함수들과 자주 함께 쓰이는 패턴 연산자
* [MySQL GROUP\_CONCAT](https://villagesql.com/docs/ko/tutorial/group-concat.md) — 그룹의 값을 하나의 문자열로 합치기


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.