CREATE CAST

CREATE CAST — 새 형변환자 정의

요약

CREATE CAST (기존자료형 AS 대상자료형)
    WITH FUNCTION 함수이름 [ (인자자료형 [, ...]) ]
    [ AS ASSIGNMENT | AS IMPLICIT ]

CREATE CAST (기존자료형 AS 대상자료형)
    WITHOUT FUNCTION
    [ AS ASSIGNMENT | AS IMPLICIT ]

CREATE CAST (기존자료형 AS 대상자료형)
    WITH INOUT
    [ AS ASSIGNMENT | AS IMPLICIT ]

설명

CREATE CAST 명령은 새 형변환자를 정의한다. 형변환자란 두 종류의 자료형을 어떻게 서로 바꿀 것인지를 지정하는 것이다. 예를 들어,

SELECT CAST(42 AS float8);

구문은 42 라는 상수를 float8 자료형으로 바꾼다. 이 때, 해당 형변환용으로 지정한 float8(int4) 함수가 사용된다. (이런 형변환 작업에서 사용할 적당한 형변환자가 없다면 오류로 처리한다.)

두 자료형은 서로(쌍방 또는 일방) 내부 임의 변환 binary coercible 될 수 있다. 이것은 형 변환이 일어날 때, 어떠한 함수도 사용하지 않고, 그냥 바꾸는 것을 말한다. 두 자료형이 내부적으로는 같은 자료형으로 처리하는 경우가 그렇다. 예를 들어, text 형과 varchar 형이 대표적인 내부 임의 변환을 하는 경우다. 내부 임의 변환이 쌍방이 아닌 경우도 있다. 예를 들어, xml 형을 text 형으로 바꿀 때는 내부 임의 변환이 가능하지만, 그 반대인 경우는 xml 문법에 맞는지 유효성 검사를 하는 함수가 필요하기 때문이다. (쌍방 내부 임의 변환인 경우를 특히 이진 호환 binary compatible 이라고 하기도 한다.)

WITH INOUT 구문을 이용해서 입출력 형변환자 I/O conversion cast 를 만들 수도 있다. 입출력 형변화자는 기존 자료형의 출력 함수를 호출하고, 대상 자료형의 입력 함수에 결과 문자열을 지정해서 처리한다. 일반적으로 많은 경우에, 이런 처리 방식은 형 변환 작업용 분리된 형 변환 함수를 각각 만드는 일을 줄인다. 입출력 형변화자는 일반 함수 기반 형변환자와 하는 일은 동일하다. 구현 방법이 다를 뿐이다.

사용자가 만드는 형 변환자는 기본적으로 명시적으로 지정해서 사용한다. 명시적 사용법은 CAST(x AS 자료형) 구문이나 x::자료형 구문을 사용한다.

AS ASSIGNMENT 옵션을 사용하면, 대상 자료형 칼럼에 값을 대입하는 경우에는 묵시적으로 형변환이 일어난다. 예를 들어 foo.f1 칼럼의 자료형이 text형인 경우:

INSERT INTO foo (f1) VALUES (42);

명령을 실행하면, integer 자료형을 text 자료형으로 바꾸는 형 변환자가 있는데, 이 변환자에 AS ASSIGNMENT 옵션 추가 되어 있다면, 그 형 변환자를 특별히 지정하지 않아도 묵시적으로 사용한다. (이런 형 변환자를 대입 형변환자 assignment cast 라고 한다.)

AS IMPLICIT 옵션을 사용하면, 어떤 상황에서 그냥 묵시적으로 형 변환을 한다. (이런 형 변환자를 묵시적 형변환자 implicit cast 라고 한다.) 다음 예제를 보자:

SELECT 2 + 4.0;

구문분석기는 두 상수를 각각 integer형과 numeric형으로 간주할 것이다. 이 때 integer + numeric 용 연산자는 없고, numeric + numeric 용 연산자만 있는데, 이 쿼리는 정상 실행 된다. integer 형이 numeric 형으로 바꾸는 AS IMPLICIT 옵션이 지정된 묵시적 형변환자가 사용되었기 때문이다. — 내부적으로 보면, 결국 구문분석기는 다음과 같이 쿼리를 재작성한다:

SELECT CAST ( 2 AS numeric ) + 4.0;

시스템 카탈로그에서는 numeric 형에서 integer 형으로 바꾸는 형 변환자도 제공한다. 이런 형변환자에 AS IMPLICIT 옵션이 있다면 — 실재로는 없다 — 구문분석기는 그냥 integer + integer 연산을 해 버릴 것이다. 그럼 앞에서 이야기한 integer형에서 numeric형으로 바꾸는 형 변환자와 충돌이 생긴다. 이렇게 되면 구문분석기는 자신이 어느 것을 선택하지 않고, 그냥 오류로 처리한다. 사용자가 결정하라고. 이런 불편함을 해결하기 위한 어느 한 쪽이 묵시적 형변환을 사용한다면, 그 반대 쪽에 대해서는 같은 묵시적 형변환으로 지정하는 것에 대해서 꼼꼼히 확인해 봐야 한다.

묵시적 형변환은 보다 엄격하게 사용하는 것이 좋다. 묵시적 형변환을 유연하게 쓰면, 그 해석 범위가 넓어져, PostgreSQL 구문 분석기는 엉뚱한 처리를 하거나, 아에 처리하지 않는 경우가 생길 수도 있다. 이런 문제점을 피하기 위한 단순한 규칙은 그 두 자료형이 일반적으로 같은 범주안에 있는 경우, 그들 사이 그 값을 보호하는 변환에 대해서만 묵시적으로 형변환을 허용하는 것이다. 예를 들어, int2 자료형을 int4 자료형으로 묵시적 형변환을 충분히 쓸 수 있지만, float8 자료형을 int4 자료형으로 바꿀 때는 대입인 경우에만 묵시적 형변환을 허용하는 것이 좋다. text 형과 int4 형 처럼 두 자료형이 서로 다른 범위에 속한 경우라면 명시적 형변환이 제일 안전하다.

참고

그럼에도 불구하고, 몇몇 경우에서, 유용성이나 표준 규약 준수 때문에, 여러가지 묵시적인 형번환을 허용해서 앞에서 언급한 것처럼 결과가 모호해지는 상황이 발생한다. 구문 분석기는 fallback heuristic을 제공한다. fallback heuristic은 자료형 유형(범주)과 이런 상황에서 바람직한 형변환이 되도록 도와주는 preferred type을 기반으로 한다. CREATE TYPE 명령 설명서 참조.

하나의 형변환자를 만드려면, 기존 자료형, 대상 자료형 두 자료형에 대해서 사용자는 USAGE 권한이 있어야 한다. 내부 임의 변환 형변환자는 슈퍼유저만 만들 수 있다. (이렇게 제한 하는 이유는 잘못 만들면, 서버가 비정상 종료 될 수 있기 때문이다.)

매개 변수

기존자료형

해당 형변환자용 기존 자료형(입력 자료형) 이름.

대상자료형

해당 형변환자용 대상 자료형(출력 자료형) 이름.

함수이름[(인자자료형 [, ...])]

형변환 작업을 할 함수 이름. 이 함수 이름에 스키마 이름도 함께 지정할 수 있다. 스키마 이름이 없으면, search_path 설정값으로 지정한 스키마 안에서 그 함수를 찾는다. 해당 함수의 반환 자료형은 이 명령에서 지정하는 대상 자료형과 같아야 한다. 이 함수의 인자에 대해서는 아래에서 설명한다. 인자 자료형을 지정하지 않는다면, 그 함수는 해당 스키마 내에서 하나만 있어야 한다.

WITHOUT FUNCTION

형변환 작업용 함수가 필요 없는 경우임을 지정한다.

WITH INOUT

해당 형변환자를 입력출력용 형변환자로 지정한다. 기존 자료형 출력 함수 반환 값을 대상 자료형 입력 함수의 인자로 사용하는 형변환자다.

AS ASSIGNMENT

문맥상 대입 연산이 일어나는 경우에 묵시적으로 호출되는 형 변환자를 만든다.

AS IMPLICIT

모든 상황에서 이 형변환자가 자동 사용될 수 있도록 지정한다.

형변환자를 만들 때 사용하는 함수는 그 인자를 한 개에서 세 개까지 지정할 수 있다. 첫번째 인자는 만들 형변환자의 기존 자료형과 같아야 한다. 또는 내부 임의 변환용이라면 바로 대상 자료형이어야 한다. 두번째 인자는 integer 이어야 하며, 대상 자료형의 길이 제한 값이다. 없는 경우는 -1을 사용한다. 세번째 인자는 boolean형으로 true면 명시적 형변환자, false면 묵시적 형변화자 함수를 뜻한다. (특이하게, 표준 SQL에서는 명시적 변환과 묵시적 변환이 서로 반대인 경우가 있다, 이 때 이 인자값을 조정해서 맞춘다. 형변환자가 사용자 정의 자료형인 경우에는 만드는 이가 이 형변환을 고민해야 하기 때문에, 세번째 인자를 사용할 필요는 없다.)

형변화자에서 사용하는 함수의 반환 자료형은 대상 자료형과 같아야 한다.

일반적으로 형변환자는 기존 자료형과 대상 자료형이 서로 다르다. 그런데, 두 자료형이 같은 경우가 있는데, 이 경우는 대상 자료형에서 해당 자료의 길이 제한을 걸 때 사용된다. 이렇게 사용하면, 자료형을 바꾼다기 보다 최대 길이를 조정하는 용도로 사용된다. (time, timestamp, timestamptz 형변화자인 경우는 윤초 처리를 위해서 허용하고 있다 - 옮긴이)

기존 자료형과 대상 자료형이 서로 다른 형변환자를 만들 때, 사용하는 함수의 인자가 하나 이상이면, 그 두번째 인자는 대상 자료형의 길이 제한으로 사용된다. 예를 들어, 어떤 값을 varchar(10) 으로 형변환해야 할 경우, 먼저 자료형 변환도 하고, 다음 그 변환된 문자열의 길이 제한도 하는 두가지 일을 동시에 해야 한다. 이런 경우 사용한다.

원본 자료형이 도메인이거나, 대상 자료형이 도메인으로 지정하는 형 변환자는 아무런 작업을 하지 않는다. 그 형변환은 그 도메인의 바탕이 되는 자료형을 대상으로 한다.

참고

사용자 정의 형변환자는 DROP CAST 명령으로 지운다.

양방향 형변환을 원하면, 각각의 형변환자를 만들어야 함을 기억해야 한다.

일반적으로 사용자 정의 자료형과 표준 문자열 자료형(text, varchar, char(n), 문자열 범주 자료형을 기반으로 하는 사용자 정의 자료형) 사이 형변환자는 만들 필요가 없다. PostgreSQL에서는 이 자료형들의 입출력 형변환은 자동으로 처리한다. 대상 자료형이 문자열 형인 경우의 자동 형변환은 대입 형변환자로 간주하지만, 기존 자료형이 문자열 형인 경우의 자동 형변환은 명시적 형변환이다. 물론 사용자 정의 형변환자를 만들어 자동 형변환자를 바꿔 이런 특성을 무시할 수는 있지만, 기존 특성을 그대로 이용하기 보다 변환자를 바꿔 작업하는 것이 더 나은 경우 외에는 잘 쓰일 일이 없다. 또 다른 이유는 기존 입출력 함수의 기능과 다르게 처리되기를 바랄 때 새 형변환자를 만들기도 한다. 하지만, 이런 작업은 독특한 상황에서나 생각해봄직한 일이다. (몇몇 내장 자료형에 대해서는 표준 SQL 요구 사항을 준수하기 위해 형변화자에서 지정한 변환 방식과 다르게 작동한다.)

관례적으로 형변환자에서 사용하는 변환 함수 이름은 대상 형변환자 이름과 같은 것을 쓴다. 이는 필수 사항은 아니지만, 권고 사항이다. 많은 사용자들이 함수 호출을 이용해 형 변환을 할 때, 대상 자료형과 같은 이름의 함수를 사용하는 익숙하기 때문이다 (typename(x) 이런 형태로). 사용자에 따라 어떤 경우는 형변환자를 더 많이 쓰고, 어떤 경우는 그냥 형변환 함수를 더 많이 쓰기도 한다. 둘 다 비정상적인 사용법이 아니다. 이런 관례적 규칙을 깨고, 마음대로 형변환 함수를 사용한다면, 많은 사람들이 의야해 할 것이다. 같은 이름을 쓸 수 없어, 새 이름을 사용할 필요는 없다. 왜냐하면, PostgreSQL에서는 같은 이름의 함수로 인자 자료형만 달리해서 여러 함수를 만들 수 있기 때문이다.

참고

윗 문장은 일반적인 경우만 이야기한 것이다. 실제로 마치 함수 처럼 사용되는 것 같지만(문법상) 그 함수가 없는 경우가 두 가지 있다. 그 첫번째는 아에 그 함수가 없는 경우다. name(x) 함수 호출인데, 그 조건에 맞는(이름이 name이고, 인자가 하나고 그 자료형은 x의 자료형인) 함수가 없는데, name이 자료형 이름이고, pg_cast 카탈로그에 x 자료형이 기존 자료형, 그 이름이 대상 자료형인, 내부 임의 변환 형변환자로 등록되어 있다면, 이런 경우 그 호출은 내부 임의 변환 형변환 호출이다. 구문은 마치 함수 호출인 것 처럼 보이지만, 실제로는 함수를 호출하지 않는다. 이와 비슷하게, 입출력 형변환인 경우인데, pg_cast 카탈로그에는 없지만, 문자열을 받아서 변환하거나, 문자열로 변환하는 형반환이 있을 수 있다. 이 때도 실 함수는 없다.

참고

또 다른 예외 경우: 복합 자료형을 문자열 자료형으로 변환하는 경우는 함수 호출 문법 형태로는 아에 호출이 불가능하다. 이 때는 CAST 문법이나, :: 표기법을 사용하는 명시적 형변환을 해야한다. 이 제약은 자동으로 제공되는 입출력 형변환자를 도입한 뒤부터 있게 되었다. 잘못된 형변환을 너무 자주 사용하는 문제가 있었기 때문이다.

예제

int4(bigint) 함수를 사용하는 bigint 형에서 int4 형으로 바꾸는 대입 형변환자를 만드는 예제:

CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;

(이 형변환자는 이미 시스템에서 제공하는 형변환자다.)

호환성

CREATE CAST 구문은 표준 SQL 구문을 따른다. 표준 SQL에는 함수를 사용하지 않는 경우와, 함수 인자를 지정하는 구문은 허용하지 않는다. 또한 AS IMPLICIT 옵션은 PostgreSQL 확장 기능이다.

관련 항목

CREATE FUNCTION, CREATE TYPE, DROP CAST