문자열 함수와 연산자
문자열 함수와 연산자 (String Functions and Operators)
문자열을 다루는 함수는 쿼리에서 가장 자주 쓰이는 기능 중 하나예요. PostgreSQL은 대소문자 변환, 부분 문자열 추출, 패딩, 정규식 검색·치환 등 정말 많은 함수를 제공하는데, 이 페이지에서 SQL 표준 문자열 함수와 그 밖의 문자열 함수들을 시그니처와 예시와 함께 정리해 볼게요.
출처: 공식문서
시작하기 전에
이 섹션의 함수·연산자는 character, character varying, text 타입의 값을 다뤄요. 특별한 언급이 없으면 함수·연산자는 text 타입을 받고 text 를 반환하도록 선언되며, character varying 인자를 그대로 받아들여요. character 타입 값은 함수나 연산자를 적용하기 전에 text 로 변환되는데, 이 과정에서 character 값의 뒤쪽 공백이 잘려요.
SQL은 인자를 쉼표가 아니라 키워드로 구분하는 일부 문자열 함수도 정의해요. PostgreSQL은 이 함수들의 일반 함수 호출 문법 버전도 함께 제공해요. 또 문자열 연결 연산자(||)는 입력 중 하나만 문자열 타입이면 비문자열 입력도 받아들여요. 다른 경우엔 text 로 명시적으로 강제 변환하면 돼요.
SQL 표준 문자열 함수·연산자
| 함수/연산자 | 설명 | 예시 |
|---|---|---|
text || text → text |
두 문자열을 연결해요. | 'Post' || 'greSQL' → PostgreSQL |
text || anynonarray → text, anynonarray || text → text |
비문자열 입력을 text로 변환한 뒤 연결해요. (비문자열이 배열 타입이면 배열 || 연산자와 모호해져서 안 되고, 배열의 텍스트 표현을 연결하려면 명시적으로 text 로 캐스팅해야 해요.) |
'Value: ' || 42 → Value: 42 |
btrim ( string text [, characters text ] ) → text |
string 의 시작과 끝에서 characters(기본은 공백)에 속한 문자만으로 이뤄진 가장 긴 문자열을 제거해요. |
btrim('xyxtrimyyx', 'xyz') → trim |
text IS [NOT] [form] NORMALIZED → boolean |
문자열이 지정된 유니코드 정규화 형식인지 확인해요. 선택 form 키워드는 NFC(기본)·NFD·NFKC·NFKD 를 지정해요. 이 표현식은 서버 인코딩이 UTF8 일 때만 쓸 수 있고, 이미 정규화된 문자열을 정규화하는 것보다 이 표현으로 확인하는 게 종종 더 빨라요. |
U&'\0061\0308bc' IS NFD NORMALIZED → t |
bit_length ( text ) → integer |
문자열의 비트 수(octet_length 의 8배)를 반환해요. |
bit_length('jose') → 32 |
char_length ( text ) → integer, character_length ( text ) → integer |
문자열의 문자 수를 반환해요. | char_length('josé') → 4 |
lower ( text ) → text |
데이터베이스 로케일 규칙에 따라 문자열을 전부 소문자로 변환해요. | lower('TOM') → tom |
lpad ( string text, length integer [, fill text ] ) → text |
fill 문자(기본은 공백)를 앞에 붙여 string 을 length 까지 늘려요. 이미 더 길면 오른쪽이 잘려요. |
lpad('hi', 5, 'xy') → xyxhi |
ltrim ( string text [, characters text ] ) → text |
string 의 시작에서 characters(기본 공백)로만 이뤄진 가장 긴 문자열을 제거해요. |
ltrim('zzzytest', 'xyz') → test |
normalize ( text [, form ] ) → text |
문자열을 지정된 유니코드 정규화 형식으로 변환해요. form 은 NFC(기본)·NFD·NFKC·NFKD. 서버 인코딩이 UTF8 일 때만 사용 가능해요. |
normalize(U&'\0061\0308bc', NFC) → U&'\00E4bc' |
octet_length ( text ) → integer |
문자열의 바이트 수를 반환해요. | octet_length('josé') → 5 (서버가 UTF8일 때) |
octet_length ( character ) → integer |
문자열의 바이트 수를 반환해요. 이 버전은 character 타입을 직접 받아서 뒤쪽 공백을 제거하지 않아요. |
octet_length('abc '::character(4)) → 4 |
overlay ( string text PLACING newsubstring text FROM start integer [ FOR count integer ] ) → text |
start 번째 문자에서 시작해 count 개 문자만큼 이어지는 부분을 newsubstring 로 교체해요. count 를 생략하면 newsubstring 의 길이가 기본값이에요. |
overlay('Txxxxas' placing 'hom' from 2 for 4) → Thomas |
position ( substring text IN string text ) → integer |
string 안에서 substring 이 처음 나타나는 시작 인덱스를 반환하고, 없으면 0이에요. |
position('om' in 'Thomas') → 3 |
rpad ( string text, length integer [, fill text ] ) → text |
fill 문자(기본 공백)를 뒤에 붙여 길이 length 까지 늘려요. 더 길면 잘려요. |
rpad('hi', 5, 'xy') → hixyx |
rtrim ( string text [, characters text ] ) → text |
string 의 끝에서 characters(기본 공백)로만 이뤄진 가장 긴 문자열을 제거해요. |
rtrim('testxxzx', 'xyz') → test |
substring ( string text [ FROM start integer ] [ FOR count integer ] ) → text |
start 번째 문자에서 시작하고(지정 시) count 문자에서 멈추는(지정 시) 부분 문자열을 추출해요. start 와 count 중 하나는 반드시 줘야 해요. |
substring('Thomas' from 2 for 3) → hom, substring('Thomas' from 3) → omas, substring('Thomas' for 2) → Th |
substring ( string text FROM pattern text ) → text |
POSIX 정규식과 일치하는 첫 부분 문자열을 추출해요. | substring('Thomas' from '...$') → mas |
substring ( string text SIMILAR pattern text ESCAPE escape text ) → text / substring ( string text FROM pattern text FOR escape text ) → text |
SQL 정규식과 일치하는 첫 부분 문자열을 추출해요. 첫 번째 형태는 SQL:2003부터, 두 번째는 SQL:1999에만 있어서 구식으로 봐요. | substring('Thomas' similar '%#"o_a#"_' escape '#') → oma |
trim ( [ LEADING | TRAILING | BOTH ] [ characters text ] FROM string text ) → text |
string 의 시작·끝·양끝(BOTH 가 기본)에서 characters(기본 공백)로만 이뤄진 가장 긴 문자열을 제거해요. |
trim(both 'xyz' from 'yxTomxx') → Tom |
trim ( [ LEADING | TRAILING | BOTH ] [ FROM ] string text [, characters text ] ) → text |
trim()의 비표준 문법이에요. |
trim(both from 'yxTomxx', 'xyz') → Tom |
unicode_assigned ( text ) → boolean |
문자열의 모든 문자가 할당된 유니코드 코드포인트면 true, 아니면 false. 서버 인코딩이 UTF8 일 때만 쓸 수 있어요. |
|
upper ( text ) → text |
로케일 규칙에 따라 전부 대문자로 변환해요. | upper('tom') → TOM |
그 밖의 문자열 함수·연산자
연결·대소문자·문자 코드
text ^@ text → boolean— 첫 문자열이 두 번째 문자열로 시작하면 true (starts_with()와 동등). 예:'alphabet' ^@ 'alph'→tascii ( text ) → integer— 인자 첫 문자의 숫자 코드를 반환해요. UTF8에서는 유니코드 코드포인트, 다른 멀티바이트 인코딩에서는 ASCII 문자여야 해요. 예:ascii('x')→120chr ( integer ) → text— 주어진 코드의 문자를 반환해요. UTF8에서는 코드포인트로 처리하고, 다른 멀티바이트 인코딩에서는 ASCII 문자여야 해요.chr(0)은 텍스트 타입이 그 문자를 저장할 수 없어 금지됐어요. 예:chr(65)→Aconcat ( val1 "any" [, val2 "any" [, ...] ] ) → text— 모든 인자의 텍스트 표현을 연결해요. NULL 인자는 무시돼요. 예:concat('abcde', 2, NULL, 22)→abcde222concat_ws ( sep text, val1 "any" [, val2 "any" [, ...] ] ) → text— 첫 인자를 구분자로 해서 나머지 인자를 연결해요. 첫 인자는 구분자 문자열이라 NULL이면 안 되고, 그 외 NULL 인자는 무시돼요. 예:concat_ws(',', 'abcde', 2, NULL, 22)→abcde,2,22initcap ( text ) → text— 각 단어의 첫 글자를 대문자, 나머지를 소문자로 변환해요. 단어는 비알파벳 문자로 구분되는 영숫자 시퀀스예요. 예:initcap('hi THOMAS')→Hi Thomascasefold ( text ) → text— 콜레이션에 따라 입력 문자열의 케이스 폴딩을 수행해요. 케이스 폴딩은 케이스 변환과 비슷하지만 목적이 달라요. 대소문자 무시 매칭을 돕는 것인 반면 케이스 변환은 특정 케이스 형태로 바꾸는 거예요. 서버 인코딩이UTF8일 때만 사용 가능해요. 보통 소문자로 바꾸지만 콜레이션에 따라 예외가 있을 수 있어요(어떤 문자는 소문자 변형이 둘 이상이거나 대문자로 폴딩되기도 해요). 문자열 길이를 바꿀 수도 있는데, 예를 들어PG_UNICODE_FAST콜레이션에서ß(U+00DF)는ss로 폴딩돼요.libc프로바이더는 케이스 폴딩을 지원하지 않아lower와 동일해요. |lower/upper— 앞서 다뤘어요.starts_with ( string text, prefix text ) → boolean—string이prefix로 시작하면 true. 예:starts_with('alphabet', 'alph')→t
부분 문자열·자르기·채우기
left ( string text, n integer ) → text— 처음n개 문자를 반환하고,n이 음수면 마지막 |n|개를 뺀 나머지를 반환해요. 예:left('abcde', 2)→abright ( string text, n integer ) → text— 마지막n개 문자를 반환하고,n이 음수면 처음 |n|개를 뺀 나머지를 반환해요. 예:right('abcde', 2)→delength ( text ) → integer— 문자열의 문자 수를 반환해요. 예:length('jose')→4substr ( string text, start integer [, count integer ] ) → text—start번째 문자에서 시작해 지정 시count문자만큼 이어지는 부분 문자열을 추출해요. (substring(string from start for count)와 동일.) 예:substr('alphabet', 3)→phabet,substr('alphabet', 3, 2)→phreverse ( text ) → text— 문자열의 문자 순서를 뒤집어요. 예:reverse('abcde')→edcbarepeat ( string text, number integer ) → text—string을number번 반복해요. 예:repeat('Pg', 4)→PgPgPgPgreplace ( string text, from text, to text ) → text—string에서 부분 문자열from의 모든 출현을to로 교체해요. 예:replace('abcdefabcdef', 'cd', 'XX')→abXXefabXXefsplit_part ( string text, delimiter text, n integer ) → text—delimiter출현에서string을 나누고n번째(1부터) 필드를 반환해요.n이 음수면 마지막에서 |n|번째 필드예요. 예:split_part('abc~@~def~@~ghi', '~@~', 2)→def,split_part('abc,def,ghi,jkl', ',', -2)→ghistrpos ( string text, substring text ) → integer—string안에서substring이 처음 나타나는 인덱스를 반환하고, 없으면 0이에요. (position(substring in string)과 같지만 인자 순서가 바뀐 것에 주의.) 예:strpos('high', 'ig')→2translate ( string text, from text, to text ) → text—string에서from집합에 속한 각 문자를to집합의 대응 문자로 교체해요.from이to보다 길면from의 남는 문자 출현은 삭제돼요. 예:translate('12345', '143', 'ax')→a2x5unistr ( text ) → text— 인자의 이스케이프된 유니코드 문자를 평가해요. 유니코드는\XXXX(4자리 16진수),\+XXXXXX(6자리),\uXXXX(4자리),\UXXXXXXXX(8자리)로 지정할 수 있고, 백슬래시는 두 번 써서 지정해요. 서버가 UTF-8이 아니면 코드포인트를 실제 서버 인코딩으로 변환하고, 불가능하면 오류를 냅니다. 문자열 상수의 유니코드 이스케이프에 대한 (비표준) 대안이에요. 예:unistr('d\0061t\+000061')→data,unistr('d\u0061t\U00000061')→data
배열/테이블 변환
string_to_array ( string text, delimiter text [, null_string text ] ) → text[]—delimiter출현에서string을 나눠text배열로 만들어요.delimiter가NULL이면 각 문자가 별도 요소가 되고, 빈 문자열이면string을 단일 필드로 취급해요.null_string이 주어지고NULL이 아니면 그 문자열과 일치하는 필드를NULL로 바꿔요. 예:string_to_array('xx~~yy~~zz', '~~', 'yy')→{xx,NULL,zz}string_to_table ( string text, delimiter text [, null_string text ] ) → setof text— 같은 규칙으로 나눈 결과를 행 집합으로 반환해요.delimiter가NULL이면 각 문자가 별도 행, 빈 문자열이면 단일 필드,null_string이 주어지면 일치 필드를NULL로 바꿔요. 예:string_to_table('xx~^~yy~^~zz', '~^~', 'yy')→xx,NULL,zzto_ascii ( string text [, encoding name|integer ] ) → text—string을 다른 인코딩에서 ASCII로 변환해요(주로 억양 제거).encoding을 생략하면 DB 인코딩을 가정해요.LATIN1,LATIN2,LATIN9,WIN1250에서만 변환이 지원돼요. 예:to_ascii('Karél')→Karel
숫자 표현 변환
to_bin ( integer|bigint ) → text— 숫자를 2의 보수 이진 표현으로 변환해요. 예:to_bin(2147483647)→1111111111111111111111111111111to_hex ( integer|bigint ) → text— 숫자를 2의 보수 16진 표현으로 변환해요. 예:to_hex(2147483647)→7fffffffto_oct ( integer|bigint ) → text— 숫자를 2의 보수 8진 표현으로 변환해요. 예:to_oct(2147483647)→17777777777
인용·해시·파싱
quote_ident ( text ) → text— SQL 문 문자열에서 식별자로 쓰기 좋게 적절히 따옴표를 붙인 문자열을 반환해요. 필요한 경우(비식별자 문자를 포함하거나 케이스 폴딩되면)에만 따옴표를 추가하고, 내장 따옴표는 제대로 두 배로 늘려요. 예:quote_ident('Foo bar')→"Foo bar"quote_literal ( text ) → text— SQL 문 문자열에서 문자열 리터럴로 쓰기 좋게 따옴표를 붙여요. 내장 작은따옴표·백슬래시는 제대로 두 배로 늘려요. NULL 입력엔 NULL을 돌려주니, 인자가 NULL일 수 있으면quote_nullable이 더 적합해요. 예:quote_literal(E'O\'Reilly')→'O''Reilly'quote_literal ( anyelement ) → text— 값을 text로 변환한 뒤 리터럴로 인용해요. 예:quote_literal(42.5)→'42.5'quote_nullable ( text ) → text— 문자열 리터럴로 쓰기 좋게 인용하고, 인자가 NULL이면NULL을 반환해요. 예:quote_nullable(NULL)→NULLquote_nullable ( anyelement ) → text— 값을 text로 변환 후 인용하거나, NULL이면NULL. 예:quote_nullable(42.5)→'42.5'md5 ( text ) → text— 인자의 MD5 해시를 16진수로 계산해요. 예:md5('abc')→900150983cd24fb0d6963f7d28e17f72parse_ident ( qualified_identifier text [, strict_mode boolean DEFAULT true ] ) → text[]—qualified_identifier를 식별자 배열로 나누고 개별 식별자의 인용을 제거해요. 기본적으로 마지막 식별자 뒤의 추가 문자는 오류로 보지만, 두 번째 인자가false면 무시해요. 함수 같은 객체의 이름 파싱에 유용해요. 길이 초과 식별자는 자르지 않고, 자르려면 결과를name[]로 캐스팅하세요. 예:parse_ident('"SomeSchema".someTable')→{SomeSchema,sometable}pg_client_encoding ( ) → name— 현재 클라이언트 인코딩 이름을 반환해요. 예:pg_client_encoding()→UTF8
정규식 함수
regexp_count ( string text, pattern text [, start integer [, flags text ] ] ) → integer—string에서 POSIX 정규식pattern이 일치하는 횟수를 반환해요. 예:regexp_count('123456789012', '\d\d\d', 2)→3regexp_instr ( string text, pattern text [, start integer [, N integer [, endoption integer [, flags text [, subexpr integer ] ] ] ] ] ) → integer—N번째 일치가 발생하는string내 위치를 반환하고, 없으면 0이에요. 예:regexp_instr('ABCDEF', 'c(.)(..)', 1, 1, 0, 'i')→3,regexp_instr('ABCDEF', 'c(.)(..)', 1, 1, 0, 'i', 2)→5regexp_like ( string text, pattern text [, flags text ] ) → boolean—string안에 POSIX 정규식pattern일치가 있는지 확인해요. 예:regexp_like('Hello World', 'world$', 'i')→tregexp_match ( string text, pattern text [, flags text ] ) → text[]—string에 대한 POSIX 정규식pattern의 첫 일치 안의 부분 문자열들을 반환해요. 예:regexp_match('foobarbequebaz', '(bar)(beque)')→{bar,beque}regexp_matches ( string text, pattern text [, flags text ] ) → setof text[]— 첫 일치 안의 부분 문자열들,g플래그를 쓰면 모든 일치 안의 부분 문자열들을 반환해요. 예:regexp_matches('foobarbequebaz', 'ba.', 'g')→{bar},{baz}regexp_replace ( string text, pattern text, replacement text [, flags text ] ) → text— POSIX 정규식pattern의 첫 일치(또는g플래그 시 모든 일치)인 부분 문자열을 교체해요. 예:regexp_replace('Thomas', '.[mN]a.', 'M')→ThMregexp_replace ( string text, pattern text, replacement text, start integer [, N integer [, flags text ] ] ) → text—string의start번째 문자부터 검색해N번째 일치(또는N이 0이면 모든 일치)를 교체해요.N생략 시 기본 1. 예:regexp_replace('Thomas', '.', 'X', 3, 2)→ThoXasregexp_split_to_array ( string text, pattern text [, flags text ] ) → text[]— POSIX 정규식을 구분자로 써string을 나눠 배열을 만들어요. 예:regexp_split_to_array('hello world', '\s+')→{hello,world}regexp_split_to_table ( string text, pattern text [, flags text ] ) → setof text— 같은 방식으로 나눠 결과 집합을 만들어요. 예:regexp_split_to_table('hello world', '\s+')→hello,worldregexp_substr ( string text, pattern text [, start integer [, N integer [, flags text [, subexpr integer ] ] ] ] ) → text— POSIX 정규식pattern의N번째 출현과 일치하는 부분 문자열을 반환하고, 없으면NULL. 예:regexp_substr('ABCDEF', 'c(.)(..)', 1, 1, 'i')→CDEF
format 함수
format 은 C의 sprintf 처럼 포맷 문자열에 따라 출력을 만드는 함수예요.
format(formatstr text [, formatarg "any" [, ...] ])
formatstr 은 결과를 어떻게 꾸밀지 지정하는 포맷 문자열이에요. 포맷 지정자(placeholder)가 있는 곳을 제외하면 문자열의 텍스트가 그대로 결과에 복사돼요. 각 formatarg 인자는 자기 타입의 일반 출력 규칙에 따라 text로 변환된 뒤, 지정자에 따라 포맷되어 결과 문자열에 들어가요.
포맷 지정자는 % 문자로 시작하며 %[position][flags][width]type 형태예요.
position(선택) —n$형태로,formatstr이후n번째 인자를 가리켜요. 생략하면 순서대로 다음 인자를 써요.flags(선택) — 현재 유일하게 마이너스(-)를 지원하며, 지정자 출력을 왼쪽 정렬해요.width가 지정돼야 효과가 있어요.width(선택) — 출력에 쓸 최소 문자 수예요. 왼쪽/오른쪽에 공백을 채워 맞추고, 너무 작은 폭은 잘리지 않고 무시돼요. 양의 정수, 다음 함수 인자를 폭으로 쓰는 별표(*),*n$형태로n번째 인자를 폭으로 쓰는 방법이 있어요. 폭이 함수 인자에서 오면 그 인자를 지정자 값 인자보다 먼저 소비하고, 폭 인자가 음수면abs(width)길이의 필드 안에서 왼쪽 정렬해요.type(필수) — 변환 타입.s는 값을 단순 문자열로(널은 빈 문자열),I는 SQL 식별자로(필요 시 큰따옴표,quote_ident와 동등, 값이 널이면 오류),L은 SQL 리터럴로 인용(널은NULL문자열로 표시,quote_nullable과 동등)해요. 특수 시퀀스%%는 리터럴%를 출력해요.
예시를 볼게요.
SELECT format('Hello %s', 'World'); -- Hello World
SELECT format('Testing %s, %s, %s, %%', 'one', 'two', 'three'); -- Testing one, two, three, %
SELECT format('INSERT INTO %I VALUES(%L)', 'Foo bar', E'O\'Reilly'); -- INSERT INTO "Foo bar" VALUES('O''Reilly')
SELECT format('|%10s|', 'foo'); -- | foo|
SELECT format('|%-10s|', 'foo'); -- |foo |
SELECT format('Testing %3$s, %2$s, %1$s', 'one', 'two', 'three'); -- Testing three, two, one
C의 sprintf 와 달리 PostgreSQL의 format 은 같은 포맷 문자열 안에서 position 필드를 가진 지정자와 아닌 지정자를 섞을 수 있고, 모든 인자를 포맷 문자열에 쓰지 않아도 돼요.
%I 와 %L 지정자는 특히 동적 SQL 문을 안전하게 만들 때 유용해요.
concat, concat_ws, format 함수는 가변 인자(variadic)라서 VARIADIC 키워드로 표시한 배열을 넘겨 값을 전달할 수도 있어요. 배열 요소는 별도의 일반 인자처럼 취급돼요. 가변 배열 인자가 NULL이면 concat·concat_ws 는 NULL을 반환하지만, format 은 NULL을 빈 배열로 봐요.