데이터 타입¶
수치형 데이터 타입¶
정수 또는 실수를 저장하기 위해 다음의 수치형 데이터 타입을 지원한다.
타입 |
Bytes |
최소값 |
최대값 |
정확/근사치 |
---|---|---|---|---|
SHORT, SMALLINT |
2 |
-32,768 |
32,767 |
정확한 수치 |
INTEGER, INT |
4 |
-2,147,483,648 |
+2,147,483,647 |
정확한 수치 |
BIGINT |
8 |
-9,223,372,036,854,775,808 |
+9,223,372,036,854,775,807 |
정확한 수치 |
NUMERIC, DECIMAL |
16 |
정밀도 p: 1 스케일 s: 0 |
정밀도 p: 38 스케일 s: 38 |
정확한 수치 |
FLOAT, REAL |
4 |
-3.402823466E+38 (ANSI/IEEE 754-1985 표준) |
+3.402823466E+38 (ANSI/IEEE 754-1985 표준) |
근사치 부동소수점: 7자리 |
DOUBLE, DOUBLE PRECISION |
8 |
-1.7976931348623157E+308 (ANSI/IEEE 754-1985 표준) |
+1.7976931348623157E+308 (ANSI/IEEE 754-1985 표준) |
근사치 부동소수점: 15자리 |
수치형 데이터 타입은 정확한(exact) 타입과 근사치(approximate) 타입으로 구분된다. 정확한 수치형 데이터 타입(SMALLINT, INT, BIGINT, NUMERIC)은 정확하고 일관된 값을 가져야 하는 경우에 사용된다. 근사치 수치형 데이터 타입(FLOAT, DOUBLE)은 리터럴 값이 같아도 시스템에 따라 다르게 해석될 수 있으므로 주의한다.
CUBRID는 수치형 데이터 타입에 대해 UNSIGNED 타입을 지원하지 않는다.
위의 표에서 두 가지 이름으로 표기한 타입들은 동일하지만, 테이블 생성 후 SHOW COLUMNS 문으로 타입의 이름을 확인할 때에는 항상 위 단어로 표기된다. 예를 들어, 테이블을 생성할 때에는 SHORT, SMALLINT 둘 다 쓸 수 있으며, SHOW COLUMNS 문으로 타입의 이름을 확인할 때에는 항상 SHORT 로 표기된다.
정밀도와 스케일(Precision and Scaling)
숫자 데이터 타입의 정밀도(precision)는 그 값이 유지할 수 있는 유효한 자릿수로 정의된다. 이는 정확한 수치형이든 근사치 수치형이든 마찬가지이다.
스케일(scale)은 소수점 이하의 자릿수를 나타내는데, 정확한 수치형에서만 의미가 있다. 정확한 수치형으로 선언된 속성은 항상 고정된 정밀도와 스케일을 갖게 된다. NUMERIC (또는 DECIMAL) 데이터 타입은 항상 최소한 한 자리의 정밀도를 갖는다. 스케일의 범위는 0과 선언된 정밀도 사이여야 한다. 스케일이 정밀도보다 클 수는 없다. INTEGER 나 SMALLINT, BIGINT 데이터 타입에서는 스케일은 0이고(즉, 소수점 이하가 없음), 정밀도는 시스템에 의해 고정된다.
수치형 리터럴(Numeric Literals)
수치형 값을 입력하기 위해서는 특별한 기호가 사용될 수 있는데, 플러스(+)는 양수를, 마이너스(-)는 음수를 나타내는 데 사용한다. 과학용 표기법이 사용될 수도 있다. 화폐 값을 표현하기 위하여 시스템에 지정된 통화 기호를 사용할 수도 있다. 수치형 리터럴로 표현 가능한 최대 정밀도는 255이다.
수치형 변환(Numeric Coercions)
모든 수치형 데이터 타입은 상호 비교 가능하고, 이를 위해 서로 공통된 수치형 데이터 타입으로 자동 변환이 이루어진다. 명시적인 변환은 CAST 연산자를 이용해야 한다. 서로 다른 수치형 데이터가 서로 정렬되거나, 수식에서 계산될 때에는 시스템에 의하여 자동으로 변환된다. 예를 들어, FLOAT 타입의 속성 값과 INTEGER 타입의 속성 값을 더하게 되면, 시스템이 자동적으로 INTEGER 속성 값을 가장 근사한 FLOAT 값으로 변환한 후 덧셈을 수행한다.
다음은 FLOAT 타입 값과 INTEGER 타입 값을 더하는 경우 FLOAT 타입 값을 출력하는 예이다.
CREATE TABLE tbl (a INT, b FLOAT); INSERT INTO tbl VALUES (10, 5.5); SELECT a + b FROM tbl;1.550000e+01
다음은 두 개의 정수 값을 더하는 경우 결과 값도 INTEGER 타입이 되기 때문에 오버플로우(overflow) 에러가 발생하는 예이다.
SELECT 100000000*1000000;ERROR: Data overflow on data type integer.위와 같은 경우 어느 한 쪽의 타입을 BIGINT로 명시하면, BIGINT로 결과 값을 결정하고, 정상적인 결과를 출력한다.
SELECT CAST(100000000 AS BIGINT)*1000000;100000000000000
Warning
CUBRID 2008 R2.0 미만 버전에서는 입력된 상수가 INTEGER 범위를 넘어서면 NUMERIC으로 처리되었으나, CUBRID 2008 R2.0 이상 버전에서는 BIGINT로 처리된다.
INT, INTEGER¶
INTEGER 데이터 타입은 정수 표현을 위해 사용하며, 표현할 수 있는 값의 범위는 -2,147,483,648에서 +2,147,483,647이다. 작은 정수를 표현하기 위해 SMALLINT를 사용하거나, 큰 정수를 표현하기 위해 BIGINT를 사용할 수 있다.
INTEGER와 INT는 같은 의미로 사용된다.
INT 타입에 실수가 입력되면, 소수점 아래 숫자가 반올림되어 정수값이 저장된다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
INTEGER에 8934를 지정하면 8934가 저장됨.
INTEGER에 7823467를 지정하면 7823467이 저장됨.
INTEGER에 89.8를 지정하면 90이 저장됨(소수점 뒤의 수치는 반올림됨).
INTEGER에 3458901122를 지정하면 오류가 발생함(표현 가능 범위를 초과하면 오류 발생).
SHORT, SMALLINT¶
SMALLINT 데이터 타입은 작은 정수 표현을 위해 사용되며, 표현할 수 있는 값의 범위는 -32,768에서 +32,767이다.
SMALLINT와 SHORT는 같은 의미로 사용된다.
SMALLINT 타입에 실수가 입력되면, 소수점 아래 숫자가 반올림되어 정수값이 저장된다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
SMALLINT에 8934를 지정하면 8934가 저장됨.
SMALLINT에 34.5를 지정하면 35가 저장됨(소수점 이하의 숫자는 반올림됨).
SMALLINT에 23467를 지정하면 23467이 저장됨.
SMALLINT에 89354를 지정하면 오류가 발생함(표현 가능 범위를 초과하면 오류 발생).
BIGINT¶
BIGINT 데이터 타입은 큰 정수 표현을 위해 사용되며, 표현할 수 있는 값의 범위는 -9,223,372,036,854,775,808에서 9,223,372,036,854,775,807이다.
BIGINT 타입에 실수가 입력되면, 소수점 아래 숫자가 반올림되어 정수값이 저장된다.
정밀도와 표현할 수 있는 범위를 기준으로는 다음과 같이 정렬할 수 있다.
SMALLINT ⊂ INTEGER ⊂ BIGINT ⊂ NUMERIC
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
BIGINT에 8934를 지정하면 8934가 저장됨.
BIGINT에 89.1을 지정하면 89가 저장됨.
BIGINT에 89.8을 지정하면 90이 저장됨(소수점 뒤의 수치는 반올림됨).
BIGINT에 3458901122를 지정하면 3458901122가 저장됨.
NUMERIC, DECIMAL¶
NUMERIC 또는 DECIMAL 데이터 타입은 고정 소수점 숫자를 표현하기 위해 사용되며, 다음과 같이 전체 자리 수(정밀도)와 소수점 아래 자릿수(스케일)을 옵션으로 지정하여 정의할 수 있다. 정밀도 p의 최소값은 1이고 최대값은 38이며, 정밀도 p가 생략되면 기본값은 15이므로, 정수부가 15자리를 초과하는 데이터를 입력할 수 없다. 또한, 스케일 s가 생략되면 스케일의 기본값은 0이므로 소수점 아래 첫째 자리에서 반올림한 정수를 반환한다.
NUMERIC [(p[, s])]
정밀도는 반드시 스케일 이상이어야 한다.
정밀도는 (데이터의 정수부 자리 수 + 스케일) 이상이 되도록 지정한다.
NUMERIC과 DECIMAL, 그리고 DEC는 같은 의미로 사용된다.
NUMERIC 타입끼리 연산한 결과 값의 정밀도와 스케일이 어떻게 달라지는지 확인하려면 수치형 데이터 타입의 산술 연산과 타입 변환을 참고한다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
NUMERIC에 12345.6789를 지정하면 12346이 저장됨(스케일 기본값은 0이므로 소수점 아래 첫째 자리에서 반올림함).
NUMERIC(4)에 12345.6789를 지정하면 오류가 발생함(정밀도는 데이터의 정수부 자릿수 이상이어야 함).
NUMERIC(3,4)를 선언하면 오류가 발생함(정밀도는 스케일 이상이어야 함).
NUMERIC(4,4)에 0.123456789를 지정하면 .1235가 저장됨(소수점 아래 다섯째 자리에서 반올림함).
NUMERIC(4,4)에 -0.123456789를 지정하면 -.1235가 저장됨(소수점 아래 다섯째 자리에서 반올림한 후, - 부호를 붙임).
FLOAT, REAL¶
FLOAT (또는 REAL) 데이터 타입은 부동 소수점 숫자를 표현하기 위해 사용된다.
정규 값(normalized value)으로 표현할 수 있는 값의 범위는 -3.402823466E+38 에서 -1.175494351E-38, 0, 그리고 +1.175494351E-38 에서+3.402823466E+38이며, 이 범위를 벗어나서 0에 가까운 값은 비정규 값(denormalized value)으로 표현한다. 이는 ANSI/IEEE 754-1985 표준을 준수한다.
정밀도 p의 최소값은 1이고 최대값은 38이며, 정밀도 p가 생략되거나 7 이하로 지정되면 단일 정밀도(single-precision, 7자리의 유효 숫자)로 표현된다. 만약 정밀도 p가 7보다 크고 38 이하이면 이중 정밀도(double-precision, 15자리의 유효 숫자)로 표현되며, DOUBLE 데이터 타입으로 변환된다.
FLOAT 데이터 타입은 7자리의 유효 자릿수를 넘는 입력 값에 대해 근사치를 저장하는 타입이므로 유효 자릿수를 넘어서는 정확한 값을 저장하려면 사용하지 않도록 주의한다.
FLOAT[(p)]
FLOAT 타입의 유효 자리 수는 7이다.
FLOAT 타입은 근사치 데이터를 저장하므로 데이터 비교 시 주의해야 한다.
FLOAT와 REAL은 같은 의미로 사용된다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
FLOAT에 16777217을 입력하면 16777216이 저장되고, 1.677722e+07이 출력된다(정밀도가 생략되면, 7개의 유효 숫자로 표현하므로 8번째 숫자를 반올림함).
FLOAT(5)에 16777217을 입력하면 16777216이 저장되고, 1.677722e+07이 출력된다(정밀도가 7 이하이면, 7개의 유효 숫자로 표현하므로 8번째 숫자를 반올림함).
FLOAT(5)에 16777.217을 입력하면 16777.216이 저장되고, 1.677722e+04가 출력된다(정밀도가 7 이하이면, 7개의 유효 숫자로 표현하므로 8번째 숫자를 반올림함).
FLOAT(10)에 16777.217를 지정하면 16777.217이 저장되고, 1.677721700000000e+04가 출력된다(정밀도가 7보다 크고 38 이하이면, DOUBLE 타입으로 변환되어 15개의 유효 숫자로 표현하므로 0을 채움).
DOUBLE, DOUBLE PRECISION¶
DOUBLE 데이터 타입은 부동 소수점 숫자를 표현하기 위해 사용된다.
정규 값(normalized value)으로 표현할 수 있는 값의 범위는 -1.7976931348623157E+308에서 -2.2250738585072014E-308, 0, 그리고 2.2250738585072014E-308에서 1.7976931348623157E+308이며, 이 범위를 벗어나서 0에 가까운 값은 비정규 값(denormalized value)으로 표현한다. 이는 ANSI/IEEE 754-1985 표준을 준수한다.
정밀도를 지정할 수 없으며, 이 타입이 지정된 데이터는 이중 정밀도(double-precision, 15자리의 유효 숫자)로 표현된다.
DOUBLE 데이터 타입은 15자리의 유효 자릿수를 넘는 입력 값에 대해 근사치를 저장하는 타입이므로 유효 자릿수를 넘어서는 정확한 값을 지정할 때에는 사용하지 않도록 주의한다.
DOUBLE의 유효 자리 수는 15자리이다.
DOUBLE 타입은 근사치 데이터를 저장하므로 데이터 비교 시 주의해야 한다.
DOUBLE과 DOUBLE PRECISION은 같은 의미로 사용된다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
DOUBLE에 1234.56789를 입력하면 1234.56789가 저장되고, 1.234567890000000e+03이 출력된다.
DOUBLE에 9007199254740993을 입력하면 9007199254740992가 저장되고, 9.007199254740992e+15가 출력된다.
Note
MONETARY 타입은 제거될 예정이며(deprecated), 더 이상 사용을 권장하지 않는다.
날짜/시간 데이터 타입¶
날짜/시간 데이터 타입은 날짜, 시간 혹은 이 두 가지를 모두 표현할 때 사용하는 데이터 타입으로 다음과 같은 데이터 타입을 지원한다.
타입 |
bytes |
최소값 |
최대값 |
비고 |
---|---|---|---|---|
DATE |
4 |
0001년 1월 1일 |
9999년 12월 31일 |
예외적으로 DATE ‘0000-00-00’을 입력할 수 있다. |
TIME |
4 |
00시 00분 00초 |
23시 59분 59초 |
|
TIMESTAMP |
4 |
1970년 1월 1일 0시 0분 1초(GMT) 1970년 1월 1일 9시 0분 1초(KST) |
2038년 1월 19일 3시 14분 7초(GMT) 2038년 1월 19일 12시 14분 7초(KST) |
예외적으로 TIMESTAMP ‘0000-00-00 00:00:00’을 입력할 수 있다. |
DATETIME |
8 |
0001년 1월 1일 0시 0분 0.000초 |
9999년 12월 31일 23시 59분 59.999초 |
예외적으로 DATETIME ‘0000-00-00 00:00:00’을 입력할 수 있다. |
TIMESTAMPLTZ |
4 |
1970년 1월1일 0시 0분 1초(GMT) 타임존에 따라 다름 |
2038년1월19일3시14분7초(GMT) 타임존에 따라 다름 |
로컬 타임존의 TIMESTAMP. 예외적으로, TIMESTAMPLTZ’0000-00-00 00:00:00’ 형태가 허용된다. |
TIMESTAMPTZ |
8 |
1970년 1월1일 0시 0분 1초(GMT) 타임존에 따라 다름 |
2038년1월19일3시14분7초(GMT) 타임존에 따라 다름 |
로컬 타임존의 TIMESTAMP. 예외적으로, TIMESTAMPTZ ‘0000-00-00 00:00:00’ 형태가 허용된다. |
DATETIMELTZ |
8 |
0001년 1월1일 0시0분 0.000초 UTC 타임존에 따라 다름 |
9999년12월31일23시59분59.999초 타임존에 따라 다름 |
로컬 타임존의 DATETIME. 예외적으로, DATETIMELTZ ‘0000-00-00 00:00:00’ 형태가 허용된다. |
DATETIMETZ |
12 |
0001년 1월1일 0시0분 0.000초 UTC 타임존에 따라 다름 |
9999년12월31일23시59분59.999초 타임존에 따라 다름 |
타임존의 DATETIME. 예외적으로, DATETIMETZ ‘0000-00-00 00:00:00’ 형태가 허용된다. |
범위와 해상도(Range and Resolution)
시간 값의 표현은 기본적으로 24시간 시스템에 의하여 그 범위가 결정된다. 날짜는 그레고리력(Gregorian calendar)을 따른다. 이 두 제약 사항을 벗어나는 값이 날짜나 시간으로 입력되면 오류가 발생한다.
DATE 중 연도의 범위는 0001~9999 AD이다.
CUBRID 2008 R3.0 버전부터는 연도를 두 자리만 표기하면, 00~69는 2000~2069로 변환되고, 70~99는 1970~1999로 변환된다. R3.0 미만 버전에서는 01~99까지의 두 자리 연도를 표기하면, 각각 0001~0099로 변환된다.
TIMESTAMP 의 범위는 GMT로 1970년 1월 1일 0시 0분 1초부터 2038년 1월 19일 03시 14분 07초까지이다. KST (GMT+9)로는 1970년 1월 1일 9시 0분 1초부터 2038년 1월 19일 12시 14분 07초까지 저장할 수 있다. GMT로 timestamp’1970-01-01 00:00:00’은 timestamp’0000-00-00 00:00:00’와 같다.
TIMESTAMPLTZ, TIMESTAMPTZ 범위는 타임존에 따라 다르지만 UTC로 변환되는 값은 1970-01-01 00:00:01과 2038-01-19 03 03:14:07 사이여야 한다.
DATETIMELTZ, DATETIMETZ 범위는 타임존에 따라 다르지만 UTC로 변환되는 값은 0001-01-01 00:00:0.000과 9999-12-31 23:59:59.999 사이여야 한다. 세션 타임존이 변경되면 데이터베이스에 저장된 값이 더 이상 유효하지 않다.
날짜, 시간, 타임스탬프와 관련된 연산은 시스템의 반올림 시스템에 따라 결과가 달라질 수 있다. 이러한 경우, 시간과 타임스탬프는 가장 근접한 초를 최소 해상도로, 날짜는 가장 근접한 날짜를 최소 해상도로 하여 결정된다.
변환(Coercion)
날짜/시간 데이터 타입의 값은 서로 똑같은 항목을 가지고 있는 경우에만 CAST 연산자를 이용한 명시적인 변환이 가능하며, 묵시적 변환은 묵시적 타입 변환 을 참고한다. 아래의 표는 명시적 변환이 가능한 타입을 설명한다. 날짜/시간 데이터 타입 간 산술 연산에 대한 내용은 날짜/시간 데이터 타입의 산술 연산과 타입 변환 을 참고한다.
명시적 변환
FROM \ TO
DATE
TIME
DATETIME
TIMESTAMP
DATE
-
X
O
O
TIME
X
-
X
X
DATETIME
O
O
-
O
TIMESTAMP
O
O
O
-
DATE, DATETIME, TIMESTAMP 타입의 연, 월, 일에는 0을 입력할 수 없으나, 예외적으로 날짜와 시간이 모두 0인 값은 허용한다. 해당 타입의 칼럼에 대한 질의 수행 시 인덱스가 있으면 이 값을 사용할 수 있다는 점에서 NULL 대신 사용하면 유용하다.
DATE, DATETIME, TIMESTAMP 타입이 인자인 일부 함수는 인자의 날짜와 시간 값이 모두 0이면 시스템 파라미터 return_null_on_function_errors 의 값에 따라 다른 값을 반환한다. return_null_on_function_errors 가 yes이면 NULL 을 반환하고 no이면 에러를 반환하며, 기본값은 no 이다.
DATE, DATETIME, TIMESTAMP 타입을 반환하는 함수들은 날짜와 시간 값이 모두 0인 값을 반환할 수 있지만 JAVA 응용 프로그램에서는 이러한 값을 Date 객체에 저장할 수 없다. 따라서 연결 URL 문자열의 zeroDateTimeBehavior 속성(Property) 설정에 따라서 예외로 처리하거나 NULL을 반환하거나 또는 최소값을 반환한다(이에 관한 자세한 내용은 연결 설정 참고).
시스템 파라미터 intl_date_lang을 설정하면
TO_DATE()
,TO_TIIME()
,TO_DATETIME()
,TO_TIMESTAMP()
,DATE_FORMAT()
,TIME_FORMAT()
,TO_CHAR()
,STR_TO_DATE()
함수의 입력 문자열 형식이 해당 로캘의 날짜 형식을 따른다. 자세한 내용은 구문/타입 관련 파라미터과 각 함수의 설명을 참고한다.타임존이 포함된 타입은 상위 타입과 동일한 변환 규칙을 따른다.
Note
날짜/시간 타입 및 타임존이 있는 날짜/시간 타입의 리터럴에 대해서는 날짜/시간을 참고한다.
DATE¶
DATE 데이터 타입은 연도(yyyy), 월(mm), 일(dd)을 표현하며, 지원 범위는 ‘01/01/0001’에서 ‘12/31/9999’까지이다. 연도는 생략 가능하며, 생략될 경우 현재 시스템의 연도 값이 자동으로 지정된다. 입력 형식은 다음과 같다.
date'mm/dd[/yyyy]'
date'[yyyy-]mm-dd'
모든 항목은 정수 형태로 입력되어야 한다.
CSQL은 ‘MM/DD/YYYY’ 형식으로 날짜 값을 출력하고, JDBC 응용 프로그램 및 CUBRID 매니저는 ‘YYYY-MM-DD’ 형식으로 날짜 값을 출력한다.
문자열 타입의 데이터를 DATE 타입으로 변환하는 함수는
TO_DATE()
이다.연, 월, 일에는 0을 입력할 수 없으나 예외적으로 연, 월, 일이 모두 0인 ‘0000-00-00’은 입력할 수 있다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
DATE'2008-10-31'은 '10/31/2008'로 출력된다.
DATE'10/31'은 '10/31/2011'으로 출력된다(연도가 생략되면 현재 연도가 자동으로 지정됨).
DATE'00-10-31'은 '10/31/2000'로 출력된다.
DATE'0000-10-31'은 에러가 출력된다(연도의 최소값은 1).
DATE'70-10-31'은 '10/31/1970'로 출력된다.
DATE'0070-10-31'은 '10/31/0070'로 출력된다.
TIME¶
TIME 데이터 타입은 시각(hh), 분(mi), 초(ss) 를 표현하며, 지원 범위는 ‘00:00:00’에서 ‘23:59:59’까지이다. 초는 생략 가능하며, 생략될 경우 0초로 지정된다. 입력 형식은 12시간 표기법(AM/PM표기법) 또는 24시간 표기법이 모두 허용되며, 다음과 같이 작성한다.
time'hh:mi[:ss] [am | pm]'
모든 항목은 정수로 입력되어야 한다.
CSQL은 항상 AM/PM 표기법으로 시간 값을 출력하고, JDBC 응용 프로그램 및 CUBRID 매니저는 24시간 표기법으로 시간 값을 출력한다.
24시간 표기법으로 시간 값을 입력할 때에도 AM/PM을 지정할 수 있으며, 이때 시간 값과 지정된 AM 또는 PM이 일치하지 않으면 오류가 발생한다.
모든 시간 값은 데이터베이스에는 24시간 표기법으로 저장된다.
문자열 타입의 데이터를 TIME 타입으로 변환하는 함수는
TO_TIME()
이다.이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
TIME'00:00:00'은 '12:00:00 AM'으로 출력된다.
TIME'1:15'는 '01:15:00 AM'으로 간주된다.
TIME'13:15:45'는 '01:15:45 PM'으로 간주된다.
TIME'13:15:45 pm'은 정상적으로 저장된다.
TIME'13:15:45 am'은 오류가 발생한다(주어진 시간 값과 AM/PM이 불일치).
TIMESTAMP¶
TIMESTAMP 데이터 타입은 날짜(연, 월, 일)와 시간(시, 분, 초)을 결합한 데이터 값을 표현하며, GMT로 ‘1970-01-01 00:00:01’부터 ‘2038-01-19 03:14:07’까지 표현할 수 있다. 이 범위를 초과하거나 밀리초 단위의 시간 데이터를 저장하는 경우라면, DATETIME 데이터 타입을 이용할 수 있다. TIMESTAMP 데이터 타입의 입력 형식은 다음과 같다.
timestamp'hh:mi[:ss] [am|pm] mm/dd[/yyyy]'
timestamp'hh:mi[:ss] [am|pm] [yyyy-]mm-dd'
timestamp'mm/dd[/yyyy] hh:mi[:ss] [am|pm]'
timestamp'[yyyy-]mm-dd hh:mi[:ss] [am|pm]'
모든 항목은 정수로 입력되어야 한다.
연도를 생략하면 기본값으로 현재 연도가 지정되고, 시간 값(시/분/초)를 생략하면 12:00:00 AM으로 지정된다.
시스템의 현재 타임스탬프 값은
SYS_TIMESTAMP
(또는SYSTIMESTAMP
,CURRENT_TIMESTAMP
) 함수를 이용하여 TIMESTAMP 데이터 타입에 저장할 수 있다.TIMESTAMP()
함수 또는TO_TIMESTAMP()
함수를 사용하면, 문자열 데이터 타입의 데이터를 TIMESTAMP 데이터 타입으로 변환할 수 있다.연, 월, 일에는 0을 입력할 수 없으나 예외적으로 연, 월, 일, 시, 분, 초가 모두 0인 ‘0000-00-00 00:00:00’은 입력할 수 있다. GMT timestamp’1970-01-01 12:00:00 AM’ 또는 KST timestamp’1970-01-01 09:00:00 AM’은 timestamp’0000-00-00 00:00:00’으로 해석된다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
TIMESTAMP'10/31'은 '12:00:00 AM 10/31/2011'으로 출력된다(연도/시간이 생략될 경우, 기본값으로 출력).
TIMESTAMP'10/31/2008'은 '12:00:00 AM 10/31/2008'로 출력된다(시간이 생략될 경우, 기본값으로 출력).
TIMESTAMP'13:15:45 10/31/2008'은 '01:15:45 PM 10/31/2008'로 출력된다.
TIMESTAMP'01:15:45 PM 2008-10-31'은 '01:15:45 PM 10/31/2008'로 출력된다.
TIMESTAMP'13:15:45 2008-10-31'은 '01:15:45 PM 10/31/2008'로 출력된다.
TIMESTAMP'10/31/2008 01:15:45 PM'은 '01:15:45 PM 10/31/2008'로 출력된다.
TIMESTAMP'10/31/2008 13:15:45'는 '01:15:45 PM 10/31/2008'로 출력된다.
TIMESTAMP'2008-10-31 01:15:45 PM'은 '01:15:45 PM 10/31/2008'로 출력된다.
TIMESTAMP'2008-10-31 13:15:45'는 '01:15:45 PM 10/31/2008'로 출력된다.
TIMESTAMP'2099-10-31 01:15:45 PM'은 오류가 발생한다(TIMESTAMP 표현 가능 범위 초과).
DATETIME¶
DATETIME 타입은 날짜(년, 월, 일)와 시간(시, 분, 초, 밀리초)을 결합한 데이터 값을 표현하며, GMT로 0001-01-01 00:00:00.000부터 9999-12-31 23:59:59.999까지 표현할 수 있다. DATETIME 타입 데이터의 입력 형식은 다음과 같다.
datetime'hh:mi[:ss[.msec]] [am|pm] mm/dd[/yyyy]'
datetime'hh:mi[:ss[.msec]] [am|pm] [yyyy-]mm-dd'
datetime'mm/dd[/yyyy] hh:mi[:ss[.ff]] [am|pm]'
datetime'[yyyy-]mm-dd hh:mi[:ss[.ff]] [am|pm]'
모든 항목은 정수로 입력되어야 한다.
연도를 생략하면 기본값으로 현재 연도가 지정되고, 시간 값(시/분/초/밀리초)를 생략하면 12:00:00.000 AM으로 지정된다.
시스템의 현재 타임스탬프 값은
SYS_DATETIME
(또는SYSDATETIME
,CURRENT_DATETIME
,CURRENT_DATETIME()
,NOW()
)를 이용하여 DATETIME 타입에 저장할 수 있다.문자열 타입의 데이터를 DATETIME 타입으로 변환하는 함수는
TO_DATETIME()
이다.연, 월, 일에는 0을 입력할 수 없으나 예외적으로 연, 월, 일, 시, 분, 초가 모두 0인 ‘0000-00-00 00:00:00’은 입력할 수 있다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
DATETIME'10/31'은 '12:00:00.000 AM 10/31/2011'으로 출력된다(연도/시간이 생략될 경우, 기본값으로 출력).
DATETIME'10/31/2008'은 '12:00:00.000 AM 10/31/2008'로 출력된다.
DATETIME'13:15:45 10/31/2008'은 '01:15:45.000 PM 10/31/2008'로 출력된다.
DATETIME'01:15:45 PM 2008-10-31'은 '01:15:45.000 PM 10/31/2008'로 출력된다.
DATETIME'13:15:45 2008-10-31'은 '01:15:45.000 PM 10/31/2008'로 출력된다.
DATETIME'10/31/2008 01:15:45 PM'은 '01:15:45.000 PM 10/31/2008'로 출력된다.
DATETIME'10/31/2008 13:15:45'는 '01:15:45.000 PM 10/31/2008'로 출력된다.
DATETIME'2008-10-31 01:15:45 PM'은 '01:15:45.000 PM 10/31/2008'로 출력된다.
DATETIME'2008-10-31 13:15:45'는 '01:15:45.000 PM 10/31/2008'로 출력된다.
DATETIME'2099-10-31 01:15:45 PM'은 '01:15:45.000 PM 10/31/2099'로 출력된다.
문자열을 날짜/시간 타입으로 CAST¶
날짜/시간 타입 문자열 권장 형식¶
CAST()
연산자를 사용하여 문자열을 날짜/시간 타입으로 변환할 때에는 문자열을 다음과 같은 형식으로 작성하는 것을 권장한다. 참고로, CAST()
연산자에서 사용하는 날짜/시간 문자열 형식은 DB 생성 시 지정하는 로캘의 영향을 받지 않는다.
또한, TO_DATE()
, TO_TIME()
, TO_DATETIME()
, TO_TIMESTAMP()
함수에서 문자열에 대한 날짜/시간 형식을 생략하는 경우에도 날짜/시간 문자열 형식을 아래와 같이 작성한다.
DATE 타입
YYYY-MM-DD MM/DD/YYYY
TIME 타입
HH:MI:SS [AM|PM]
DATETIME 타입
YYYY-MM-DD HH:MI:SS[.msec] [AM|PM] HH:MI:SS[.msec] [AM|PM] YYYY-MM-DD MM/DD/YYYY HH:MI:SS[.msec] [AM|PM] HH:MI:SS[.msec] [AM|PM] MM/DD/YYYY
TIMESTAMP 타입
YYYY-MM-DD HH:MI:SS [AM|PM] HH:MI:SS [AM|PM] YYYY-MM-DD MM/DD/YYYY HH:MI:SS [AM|PM] HH:MI:SS [AM|PM] MM/DD/YYYY
날짜/시간 타입 문자열 허용 형식¶
CAST()
연산자는 날짜/시간 문자열에 대해 아래와 같은 형식을 허용한다.
DATE 문자열 허용 형식
[year sep] month sep day
2011-04-20 : 2011년 4월 20일
04-20 : 올해 4월 20일
구분자(sep)가 빗금(/)일 때에는 다음과 같은 순서로 인식한다.
month/day[/year]
04/20/2011 : 2011년 4월 20일
04/20 : 올해 4월 20일
구분자(sep)를 사용하지 않을 때에는 다음과 같은 형식으로 인식한다. 연도는 한 자리, 두 자리, 네 자리를 허용하고, 월은 한 자리, 두 자리를 허용한다. 일은 항상 두 자리를 입력해야 한다.
YYYYMMDD YYMMDD YMMDD MMDD MDD
20110420 : 2011년 4월 20일
110420 : 2011년 4월 20일
420 : 올해 4월 20일
TIME 문자열 허용 형식
[hour]:min[:[sec]][.[msec]] [am|pm]
09:10:15.359 am : 오전 9시 10분 15초(0.359초는 버림)
09:10:15 : 오전 9시 10분 15초
09:10 : 오전 9시 10분
:10 : 오전 12시 10분
[[[[[[Y]Y]Y]Y]M]MDD]HHMISS[.[msec]] [am|pm]
20110420091015.359 am : 오전 9시 10분 15초
0420091015 : 오전 9시 10분 15초
[H]HMMSS[.[msec]] [am|pm]
091015.359 am : 오전 9시 10분 15초
91015 : 오전 9시 10분 15초
[M]MSS[.[msec]] [am|pm]
1015.359 am : 오전 12시 10분 15초
1015 : 오전 12시 10분 15초
[S]S[.[msec]] [am|pm]
15.359 am : 오전 12시 0분 15초
15 : 오전 12시 0분 15초
Note
CUBRID 2008 R3.1 이하 버전에서는 [H]H 형식을 허용했다. 즉 R3.1 이하 버전에서 문자열 ‘10’은 TIME’10:00:00’으로 변환되었으나, R4.0부터는 TIME’00:00:10’ 으로 변환된다.
DATETIME 문자열 허용 형식
[year sep] month sep day [sep] [sep] hour [sep min[sep sec[.[msec]]]]
04-20 09 : 올해 4월 20일 오전 9시
month/day[/year] [sep] hour [sep min [sep sec[.[msec]]]]
04/20 09 : 올해 4월 20일 오전 9시
year sep month sep day sep hour [sep min[sep sec[.[msec]]]]
2011-04-20 09 : 2011년 4월 20일 오전 9시
month/day/year sep hour [sep min[sep sec [.[msec]]]]
04/20/2011 09 : 2011년 4월 20일 오전 9시
YYMMDDH (시간이 한 자리 수일 때에만 허용)
1104209 : 2011년 4월 20일 오전 9시
YYMMDDHHMI[SS[.msec]]
1104200910.359 : 2011년 4월 20일 오전 9시 10분(0.359초는 버림)
110420091000.359 : 2011년 4월 20일 오전 9시 10분 0.359초
YYYYMMDDHHMISS[.msec]
201104200910.359 : 2020년 11월 4일 오후 8시 9분 10.359초
20110420091000.359 : 2011년 4월 20일 오전 9시 10분 0.359초
시간-날짜 순서의 문자열 허용 형식
[hour]:min[:sec[.msec]] [am|pm] [year-]month-day
09:10:15.359 am 2011-04-20 : 2011년 4월 20일 오전 9시 10분 15.359초
:10 04-20 : 올해 4월 20일 오전 12시 10분
[hour]:min[:sec[.msec]] [am|pm] month/day[/[year]]
09:10:15.359 am 04/20/2011 : 2011년 4월 20일 오전 9시 10분 15.359초
:10 04/20 : 올해 4월 20일 오전 12시 10분
hour[:min[:sec[.[msec]]]] [am|pm] [year-]month-day
09:10:15.359 am 04-20 : 올해 4월 20일 오전 9시 10분 15.359초
09 04-20 : 올해 4월 20일 오전 9시
hour[:min[:sec[.[msec]]]] [am|pm] month/day[/[year]]
09:10:15.359 am 04/20 : 올해 4월 20일 오전 9시 10분 15.359초
09 04/20 : 올해 4월 20일 오전 9시
규칙
msec은 밀리초를 나타내는 일련의 숫자이다. 앞에서 네 번째 자리부터 이후의 숫자는 무시된다. 값 사이를 구분하는 구분자의 규칙은 다음과 같다.
TIME 문자열은 시간 구분자로 항상 하나의 콜론(:)을 사용해야 한다.
DATE 와 DATETIME 문자열은 구분자 없이 연속된 숫자로 나타낼 수 있고, DATETIME 문자열은 시간과 날짜를 공백으로 구분할 수 있다.
입력 문자열 안에서 구분자들은 동일해야 한다.
시간-날짜 순서의 문자열은 시간 구분자로 콜론(:)만 사용할 수 있으며, 날짜 구분자로는 하이픈(-)이나 빗금(/)만 사용할 수 있다. 날짜 입력 시 하이픈을 사용하는 경우 yyyy-mm-dd 순으로 입력하며, 빗금(/)을 사용하는 경우 mm/dd/yyyy 순으로 입력한다.
날짜 부분의 문자열에는 다음 규칙이 적용된다.
연도는 구문이 허용하는 한 생략할 수 있다.
연도를 두 자리로 입력하면 1970년~2069년 범위의 연도를 나타낸다. 즉, YY<70 이면 2000+YY으로 처리하고, YY>=70이면 1900+YY으로 처리한다. 한 자리나 세 자리, 네 자리 숫자로 연도를 입력하면 해당 숫자 그대로를 나타낸다.
문자열 앞뒤의 공백과 뒤의 문자열은 무시된다. DATETIME, TIME 문자열을 위한 am/pm 지정자는 시간 값의 일부로 인식하지만, 공백이 아닌 문자가 뒤에 붙으면 am/pm 지정자로 인식되지 않는다.
CUBRID의 TIMESTAMP 타입은 DATE 타입과 TIME 타입으로 구성되고, DATETIME 타입은 DATE 타입과 TIME 타입에 밀리초(milliseconds)가 더해져서 구성된다. 입력 문자열은 날짜(DATE 문자열), 시간(TIME 문자열), 혹은 둘 다(DATETIME 문자열) 포함할 수 있다. 특정 타입의 데이터를 보유한 문자열은 다른 타입으로도 변환될 수 있으며 다음과 같은 규칙이 적용된다.
DATE 문자열을 DATETIME 타입으로 변환하면 시간 값은 ‘00:00:00’이 된다.
TIME 문자열을 DATETIME 타입으로 변환하면 콜론(:)이 날짜 구분자로 인식되어 TIME 문자열이 날짜를 나타내는 문자열로 인식되고, 시간 값은 ‘00:00:00’이 된다.
DATETIME 문자열을 DATE 타입으로 변환하면 결과값에서 시간 부분은 무시되지만, 시간 입력값의 형식은 유효해야 한다.
DATETIME 문자열을 TIME 타입으로 변환할 수 있지만, 다음과 같은 규칙이 적용된다.
문자열에 있는 날짜와 시간은 최소한 하나의 공백에 의해 구분되어야 한다.
결과값에서 날짜 부분은 무시되지만, 날짜 입력값의 형식이 유효해야 한다.
날짜 부분의 연도가 4자리 이상이거나(0으로 시작할 수 있음), 시간 부분이 최소한 시와 분([H]H:[M]M)을 포함해야 한다. 그렇지 않으면 날짜 부분이 [MM]SS 포맷의 TIME 타입으로 인식되고, 뒤이어 나오는 문자열은 무시된다.
DATETIME 문자열의 각 단위(년, 월, 일, 시, 분, 초) 중 하나가 999999보다 크면, 숫자가 아닌 것으로 인식하여 해당 단위가 포함된 문자열이 무시된다. 예를 들어 ‘2009-10-21 20:9943:10’은 분 단위의 값이 범위를 벗어나므로 에러가 발생한다. 그러나 ‘2009-10-21 20:1000123:10’이 입력되면 ‘2009’를 MMSS 포맷의 TIME 타입으로 인식하여 TIME’00:20:09’를 반환한다.
시간-날짜 순서의 문자열을 TIME 타입으로 변환하면 문자열의 날짜 부분은 무시되지만, 날짜 부분의 형식은 유효해야 한다.
시간 부분이 있는 모든 입력 문자열은 변환 시 [msec] 을 허용하지만, DATETIME 타입만 그 값을 유지한다. DATE, TIMESTAMP, TIME 와 같은 타입으로 변환하면 msec 값을 버린다.
DATETIME, TIME 문자열에서의 모든 변환은 시간 값 뒤에 나오는 영문 로캘(locale) 또는 서버의 현재 로캘로 쓰여진 am/pm 지정자를 허용한다.
SELECT CAST('420' AS DATE);cast('420' as date) ====================== 04/20/2012SELECT CAST('91015' AS TIME);cast('91015' as time) ======================== 09:10:15 AMSELECT CAST('110420091035.359' AS DATETIME);cast('110420091035.359' as datetime) ======================================= 09:10:35.359 AM 04/20/2011SELECT CAST('110420091035.359' AS TIMESTAMP);cast('110420091035.359' as timestamp) ======================================== 09:10:35 AM 04/20/2011
타임존이 있는 날짜/시간 데이터 타입¶
타임존이 있는 날짜/시간 데이터 타입은 타임존을 명시하여 입력하거나 출력할 수 있는 날짜/시간 타입이다. 타임존을 설정하는 방법은 지역 이름을 명시하는 방법과 시간의 오프셋을 명시하는 방법이 있다.
기존의 날짜/시간 타입 이름 뒤에 TZ 또는 LTZ가 붙어 있는 경우 타임존 정보를 고려하게 되는데, TZ는 타임존을 의미하며, LTZ는 로컬 타임존을 의미한다.
TZ 타입은 <date/time type> WITH TIME ZONE으로도 표현이 가능하다. 내부적으로 UTC 시간과 생성 시 타임존 정보(사용자가 명시하거나 세션 타임존에 의해 결정됨)를 저장한다. TZ 타입은 타임존을 저장하기 위해 4바이트가 추가로 필요하다.
LTZ 타입은 <date/time type> WITH LOCAL TIME ZONE으로도 표현이 가능하다. 내부적으로 UTC 시간을 저장하며, 출력 시 로컬(현재의 세션) 타임존으로 변환된다.
타임존이 없는 타입과 비교하기 위해, 다음 표에는 타임존이 없는 타입과 타임존이 있는 타입을 함께 설명하였다.
표의 설명에 있는 UTC는 협정 세계시(Coordinated Universal Time)를 나타낸다.
구분 |
타입 |
입력 |
저장 |
출력 |
설명 |
---|---|---|---|---|---|
DATE |
DATE |
타임존 비포함 |
입력 값 |
절대 값(입력 값과 동일) |
날짜 |
DATETIME |
DATETIME |
타임존 비포함 |
입력 값 |
절대 값(입력 값과 동일) |
밀리초를 포함한 날짜/시간 |
DATETIMETZ |
타임존 포함 |
UTC + 타임존(지역 또는 오프셋) |
절대 값(입력한 타임존 유지) |
날짜/시간 + 타임존 정보 |
|
DATETIMELTZ |
타임존 포함 |
UTC |
상대 값(세션 타임존에 따라 변환됨) |
세션 타임존에서의 날짜/시간 |
|
TIME |
TIME |
타임존 비포함 |
입력 값 |
절대 값(입력 값과 동일) |
시간 |
TIMESTAMP |
TIMESTAMP |
타임존 비포함 |
UTC |
상대 값(세션 타임 존에 따라 변환됨) |
입력 값을 세션 타임존의 값으로 해석함 |
TIMESTAMPTZ |
타임존 포함 |
UTC + 타임존(지역 또는 오프셋) |
절대 값(입력한 타임존 유지) |
UTC + 타임존이 있는 타임스탬프 |
|
TIMESTAMPLTZ |
타임존 포함 |
UTC |
상대 값(세션 타임존에 따라 변환됨) |
세션 타임존. TIMESTAMP의 값과 같음. 출력할 때 타임존 지정자를 포함함 |
타임존이 있는 날짜/시간 타입의 최대값, 최소값, 범위와 해상도 등 나머지 특징들은 일반적인 날짜/시간 타입의 특징과 동일하다.
Note
CUBRID에서, TIMESTAMP가 1970년 1월 1일 UTC 이후 경과된 ‘초’로 보관된다(UNIX 시간).
타 DBMS의 TIMESTAMP는 CUBRID 의 DATETIME 과 비슷한 방식이며 ‘milliseconds’를 보관한다.
타임존 타입을 사용하는 함수의 예를 보려면 다음을 참고한다. 날짜/시간 함수와 연산자
다음은 세션 타임존의 변경에 따라 DATETIME, DATETIMETZ와 DATETIMELTZ의 출력 값이 다르게 나타나는 예이다.
-- csql> ;set timezone="+09"
CREATE TABLE tbl (a DATETIME, b DATETIMETZ, c DATETIMELTZ);
INSERT INTO tbl VALUES (datetime'2015-02-24 12:30', datetimetz'2015-02-24 12:30', datetimeltz'2015-02-24 12:30');
SELECT * FROM tbl
12:30:00.000 PM 02/24/2015 12:30:00.000 PM 02/24/2015 +09:00 12:30:00.000 PM 02/24/2015 +09:00
-- csql> ;set timezone="+07"
SELECT * FROM tbl;
12:30:00.000 PM 02/24/2015 12:30:00.000 PM 02/24/2015 +09:00 10:30:00.000 AM 02/24/2015 +07:00
다음은 세션 타임존의 변경에 따라 TIMESTAMP, TIMESTAMPTZ와 TIMESTAMPLTZ의 출력 값이 다르게 나타나는 예이다.
-- ;set timezone="+09"
CREATE TABLE tbl (a TIMESTAMP, b TIMESTAMPTZ, c TIMESTAMPLTZ);
INSERT INTO tbl VALUES (timestamp'2015-02-24 12:30', timestamptz'2015-02-24 12:30', timestampltz'2015-02-24 12:30');
SELECT * FROM tbl;
12:30:00 PM 02/24/2015 12:30:00 PM 02/24/2015 +09:00 12:30:00 PM 02/24/2015 +09:00
-- csql> ;set timezone="+07"
SELECT * FROM tbl;
10:30:00 AM 02/24/2015 12:30:00 PM 02/24/2015 +09:00 10:30:00 AM 02/24/2015 +07:00
문자열을 TIMESTAMP 타입으로 변환
문자열을 timestamp/timestampltz/timestamptz로 변환하는 작업은 문자열로부터 TIMESTAMP 객체를 생성하는 과정에서 수행된다.
From/to |
Timestamp |
Timestampltz |
Timestamptz |
---|---|---|---|
String (타임존 생략) |
세션 타임존으로 날짜/시간을 UTC로 변환하고 Unix 시간으로 인코딩하여 저장 |
세션 타임존으로 날짜/시간을 UTC로 변환하고 Unix 시간으로 인코딩하여 저장 |
세션 타임존으로 날짜/시간을 UTC로 변환하고 Unix 시간과 세션의 TZ_ID로 인코딩하여 저장 |
String (타임존 포함) |
오류 (timestamp 에서는 타임존을 허용 하지 않음) |
문자열의 타임존으로 날짜/시간을 UTC로 변환하고 Unix 시간으로 인코딩하여 저장 |
문자열의 타임존으로 날짜/시간을 UTC로 변환하고 Unix 시간과 세션의 TZ_ID로 인코딩하여 저장 |
문자열을 DATETIME 타입으로 변환
문자열을 datetime/datetimeltz/datetimetz로 변환하는 작업은 문자열로부터 DATETIME 객체를 생성하는 과정에서 수행된다.
From/to |
Datetime |
Datetimeltz |
Datetimetz |
---|---|---|---|
String (타임존 생략) |
문자열에서 분석된 값을 저장 |
세션 타임존으로 날짜/시간을 UTC로 변환하고 새로운 값들로 저장 |
세션 타임존으로 날짜/시간을 UTC로 변환하고 새로운 값과 세션의 TZ_ID로 저장 |
String (타임존 포함) |
오류 (datetime 에서는 타임존을 허용 하지 않음) |
문자열의 타임존으로 날짜/시간을 UTC로 변환하고 새로운 값들로 저장 |
문자열의 타임존으로 날짜/시간을 UTC로 변환하고 새로운 값과 세션의 TZ_ID로 저장 |
DATETIME 및 TIMESTAMP 타입을 문자열로 변환
From/to |
String (타임존 출력 불허) |
String (타임존 강제출력) |
String (타임존 비요청 - 자동 선택) |
---|---|---|---|
TIMESTAMP |
세션 타임존으로 Unix 시간을 디코딩한 후 출력 |
세션 타임존으로 Unix 시간을 디코딩한 후 세션 타임존 문자열과 함께 출력 |
세션 타임존으로 Unix 시간을 디코딩한 후 출력. 세션 타임존 문자열은 출력하지 않음 |
TIMESTAMPLTZ |
세션 타임존으로 Unix 시간을 디코딩한 후 출력 |
세션 타임존으로 Unix 시간을 디코딩한 후 세션 타임존 문자열과 함께 출력 |
세션 타임존으로 Unix 시간을 디코딩한 후 출력. 세션 타임존 문자열 출력 |
TIMESTAMPTZ |
값의 타임존으로 Unix 시간을 디코딩한 후 출력 |
값의 타임존으로 Unix 시간을 디코딩한 후 값의 타임존 문자열과 함께 출력 |
값의 타임존으로 Unix 시간을 디코딩한 후 출력. 값의 타임존 문자열 출력 |
DATETIME |
저장된 값을 출력 |
세션 타임존 문자열과 함께 저장된 값을 출력 |
저장된 값을 출력. 타임존 문자열은 출력하지 않음 |
DATETIMELTZ |
세션 타임존으로 UTC 값을 변환후 출력 |
세션 타임존으로 UTC 값을 변환 후 세션 타임존 문자열과 함께 출력 |
세션 타임존으로 UTC 값을 변환후 출력. 세션 타임존 문자열 출력 |
DATETIMETZ |
값의 타임존으로 UTC 값을 변환후 출력 |
값의 타임존으로 UTC 값을 변환 후 값의 타임존 문자열과 함께 출력 |
값의 타임존으로 UTC 값을 변환후 출력. 값의 타임존 문자열 출력 |
타임존 설정¶
다음은 cubrid.conf 파일에서 설정하는 타임존 관련 파라미터들이다. 파라미터의 설정과 관련해서는 cubrid.conf 설정 파일과 기본 제공 파라미터를 참고한다.
timezone
세션에 대한 타임존을 설정하며, 기본값은 server_timezone의 값이다.
server_timezone
서버에 대한 타임존을 설정하며, 기본값은 OS의 타임존이다.
tz_leap_second_support
윤초(leap second)에 대한 지원 여부를 yes 또는 no로 설정하며, 기본값은 no이다.
타임존 함수¶
다음은 타임존과 관련된 함수들이다. 설명을 보려면 각 함수의 이름을 클릭한다.
타임존 타입을 사용하는 함수¶
DATETIME, TIMESTAMP, TIME 타입의 값을 입력 값으로 사용하는 함수들은 모두 타임존 타입을 사용할 수 있다.
다음은 타임존 타입 값을 사용하는 예인데, 타임존이 없는 경우와 동일하게 동작한다. 다만, LTZ로 끝나는 타입의 경우 출력 값은 로컬 타임존의 설정(timezone 파라미터)을 따른다.
다음 예에서 숫자의 기본 단위는 DATETIME 타입의 최소 단위인 밀리초이다.
SELECT datetimeltz '09/01/2009 03:30:30 pm' + 1;
03:30:30.001 PM 09/01/2009 Asia/Seoul
SELECT datetimeltz '09/01/2009 03:30:30 pm' - 1;
03:30:29.999 PM 09/01/2009 Asia/Seoul
다음 예에서 숫자의 기본 단위는 TIMESTAMP 타입의 최소 단위인 초이다.
SELECT timestamptz '09/01/2009 03:30:30 pm' + 1;
03:30:31 PM 09/01/2009 Asia/Seoul
SELECT timestamptz '09/01/2009 03:30:30 pm' - 1;
03:30:29 PM 09/01/2009 Asia/Seoul
SELECT EXTRACT (hour from datetimetz'10/15/1986 5:45:15.135 am Europe/Bucharest');
5
이름이 LTZ로 끝나는 타입은 출력 시 로컬 타임존의 설정을 따른다. 따라서 아래 예와 같이 timezone 파라미터의 값이 ‘Asia/Seoul’로 설정되어 있다면 EXTRACT 함수는 해당 타임존의 시(hour)를 출력한다.
-- csql> ;set timezone='Asia/Seoul'
SELECT EXTRACT (hour from datetimeltz'10/15/1986 5:45:15.135 am Europe/Bucharest');
12
타임존 타입에 대한 변환 함수¶
다음은 문자열에서 날짜/시간 타입 값으로 변환하거나 반대로 날짜/시간 타입 값에서 문자열로 변환하는 함수들인데, 이들의 입력 값에는 오프셋, 존, 일광 절약과 같은 타임존 정보가 추가될 수 있다.
각 함수들의 사용 방법은 함수 이름을 클릭하여 해당 함수의 설명을 참고한다.
SELECT DATE_FORMAT (datetimetz'2012-02-02 10:10:10 Europe/Zurich CET', '%TZR %TZD %TZH %TZM');
SELECT STR_TO_DATE ('2001-10-11 02:03:04 AM Europe/Bucharest EEST', '%Y-%m-%d %h:%i:%s %p %TZR %TZD');
SELECT TO_CHAR (datetimetz'2001-10-11 02:03:04 AM Europe/Bucharest EEST');
SELECT TO_DATETIME_TZ ('2001-10-11 02:03:04 AM Europe/Bucharest EEST');
SELECT TO_TIMESTAMP_TZ ('2001-10-11 02:03:04 AM Europe/Bucharest');
Note
TO_TIMESTAMP_TZ()
, TO_DATETIME_TZ()
함수는 날짜/시간 인자에 TZR, TZD, TZH 및 TZM 정보를 포함할 수 있다는 것을 제외하고는 TO_TIMESTAMP()
및 TO_DATETIME()
함수와 동일하다.
타임존의 지역 이름은 IANA(Internet Assigned Numbers Authority) 타임존 데이터베이스에 있는 지역을 사용하는데, IANA 타임존에 대해서는 http://www.iana.org/time-zones을 참고한다.
IANA 타임존¶
IANA(Internet Assigned Numbers Authority) 타임존 데이터베이스에는 수많은 세계 대표 장소에 대한 지역 시간의 역사를 표현하는 코드와 데이터가 들어 있다.
이 데이터베이스는 타임 존 경계, UTC 오프셋, 그리고 일광 절약 규칙에 대해 정치체에 의해 변경된 사항을 반영하기 위해 정기적으로 업데이트되고 있으며, 관리 절차는 BCP 175: Procedures for Maintaining the Time Zone Database. <http://tools.ietf.org/html/rfc6557>에 설명되어 있다. 자세한 사항은 http://www.iana.org/time-zones를 참고한다.
CUBRID는 IANA 타임존을 지원하며, CUBRID 설치 패키지에 포함되어 있는 IANA 타임존 라이브러리를 그대로 사용할 수 있다. 최신 타임존으로 업데이트하고 싶은 경우 타임존 데이터를 업데이트하고, 타임존 라이브러리를 컴파일한 후 데이터베이스를 재구동해야 한다.
이와 관련하여 타임존 라이브러리 컴파일을 참고한다.
비트열 데이터 타입¶
비트열은 0과 1로 이루어진 이진 값의 순열(sequence)이다. CUBRID는 두 가지 비트열을 지원한다.
고정길이 비트열(BIT)
가변길이 비트열(BIT VARYING)
메서드의 인자나 속성의 타입으로 비트열을 사용할 수 있으며, 비트열 리터럴은 2진수 형식이나 16진수 형식을 사용한다. 2진수 형식으로 사용할 때에는 다음과 같이 문자 B 뒤에 0과 1로 이루어진 문자열을 붙이거나, 0b 뒤에 값을 붙여 표현한다.
B'1010'
0b1010
16진수 형식은 대문자 X 뒤에 0-9 그리고 A-F 문자로 이루어진 문자열을 붙이거나 0x 뒤에 값을 붙여 표현한다. 예를 들어, 아래는 앞에서 2진수로 표현한 것과 같은 값을 16진수로 나타낸 것이다.
X'a'
0xA
16진수에서 사용되는 문자는 대소문자를 구분하지 않는다. 즉, X’4f’와 X’4F’는 같은 값으로 간주한다.
길이(Length)
비트열이 테이블 속성이나 메서드 선언에 사용될 때에는 최대 길이를 표시해야 한다. 비트열이 가질 수 있는 최대 길이는 1,073,741,823비트이다.
비트열의 변환(Bit String Coercion)
고정길이와 가변길이 비트열 간에는 서로 비교를 위하여 자동 변환이 이루어진다. 명시적인 변환은 CAST 연산자를 이용해야 한다.
BIT(n)¶
고정길이 2진수 혹은 16진수 비트열은 BIT (n)로 나타내는데, 여기서 n 은 최대 비트의 개수를 나타낸다. 만약, n 이 생략되면 길이는 1로 지정된다. 비트열은 8비트 단위로 왼쪽부터 값이 채워진다. 예를 들어, B’1’의 값은 B’10000000’과 같은 값으로 출력된다. 따라서, 8비트 단위로 길이를 선언하고 8비트 단위로 값을 입력할 것을 권장한다.
Note
BIT(4)로 선언된 칼럼에 B’1’을 INSERT하면 CSQL에서는 X’8’로 출력되고, CUBRID Manager에서는 X’80’으로 출력된다.
n 은 0보다 큰 숫자여야 한다.
비트열의 크기가 n 을 넘어설 경우에는 절삭되고, 0으로 채워진다.
n 보다 작은 비트열이 저장될 때에는 나머지 오른쪽 부분이 0으로 채워진다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
CREATE TABLE bit_tbl(a1 BIT, a2 BIT(1), a3 BIT(8), a4 BIT VARYING);
INSERT INTO bit_tbl VALUES (B'1', B'1', B'1', B'1');
INSERT INTO bit_tbl VALUES (0b1, 0b1, 0b1, 0b1);
INSERT INTO bit_tbl(a3,a4) VALUES (B'1010', B'1010');
INSERT INTO bit_tbl(a3,a4) VALUES (0xaa, 0xaa);
SELECT * FROM bit_tbl;
a1 a2 a3 a4
=========================================================================
X'8' X'8' X'80' X'8'
X'8' X'8' X'80' X'8'
NULL NULL X'a0' X'a'
NULL NULL X'aa' X'aa'
BIT VARYING(n)¶
가변길이 비트열은 BIT VARYING (n)으로 나타낸다. 여기서 n 은 최대 비트의 개수를 나타낸다. 만약, n 이 생략되면 최대 길이인 1,073,741,823으로 지정된다. 비트열은 8비트 단위로 왼쪽부터 값이 채워진다. 예를 들어, B’1’의 값을 입력하면 B’10000000’과 같은 값으로 출력된다. 따라서, 8비트 단위로 크기를 선언하고 8비트 단위로 값을 입력할 것을 권장한다.
Note
BIT VARYING(4)로 선언된 칼럼에 B’1’을 INSERT하면 CSQL에서는 X’8’로 출력되고, CUBRID Manager 또는 응용 프로그램에서는 X’80’으로 출력된다.
비트열의 크기가 n 을 넘어설 경우에는 절삭되고 0으로 채워진다.
n 보다 작은 비트열이 저장될 때에도 나머지 부분이 0으로 채워지지 않는다.
n 은 0보다 큰 숫자여야 한다.
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
CREATE TABLE bitvar_tbl(a1 BIT VARYING, a2 BIT VARYING(8));
INSERT INTO bitvar_tbl VALUES (B'1', B'1');
INSERT INTO bitvar_tbl VALUES (0b1010, 0b1010);
INSERT INTO bitvar_tbl VALUES (0xaa, 0xaa);
INSERT INTO bitvar_tbl(a1) VALUES (0xaaa);
INSERT INTO bitvar_tbl(a2) VALUES (0xaaa);
SELECT * FROM bitvar_tbl;
a1 a2
============================================
X'8' X'8'
X'a' X'a'
X'aa' X'aa'
X'aaa' NULL
NULL X'aa'
문자열 데이터 타입¶
CUBRID는 두 종류의 문자열(character string) 타입을 지원한다.
고정길이 문자열 : CHAR (n)
가변길이 문자열 : VARCHAR (n)
Note
NCHAR, NCHAR VARYING 은 9.0 버전부터 더 이상 지원하지 않으며, 대신 CHAR, VARCHAR 타입을 사용하도록 한다.
다음은 문자열 타입을 사용할 때 적용되는 규칙이다.
문자열은 작은 따옴표로 감싸서 표현한다. SQL 구문 관련 파라미터인 ansi_quotes 의 값에 따라 문자열을 감싸는 부호로 큰 따옴표도 사용할 수 있다. ansi_quotes 값을 no로 설정하면 큰 따옴표로 감싼 문자열을 식별자로 처리하지 않고 문자열로 처리한다. 기본값은 yes 이다. 자세한 설명은 구문/타입 관련 파라미터 를 참고한다.
ANSI 표준에 따라 두 개의 문자열 사이에 공간으로 취급할 수 있는 문자(예: 공백, 탭, 줄바꿈 등)가 있다면, 두 개의 문자열은 연속된 하나의 문자열로 취급된다. 예를 들면, 다음과 같이 두 개의 문자열 사이에 줄바꿈이 있는 경우가 있다.
'abc' 'def'
위 문자열은 아래에 있는 하나의 문자열과 동일하다.
'abcdef'
작은 따옴표 자체를 문자열에 포함시키려면, 두 개의 작은 따옴표를 연속으로 입력하면 된다. 예를 들어, 아래의 왼쪽 문자열은 실제로 오른쪽과 같이 저장된다.
'''abcde''fghij' 'abcde'fghij
모든 문자열에 대한 토큰의 최대 크기는 16KB이다.
특정 국가의 언어를 입력하고자 하는 경우 DB 생성 시 언어의 로캘 이름과 문자셋을 지정하며, 이후 CHARSET 소개자(혹은 COLLATE 수정자)에 의해 로캘을 변경하여 사용할 수도 있다. 이에 대한 자세한 설명은 다국어 개요 을 참고한다.
길이(Length)
문자의 개수를 지정한다.
입력된 문자열이 지정된 길이를 초과하는 경우, 지정된 길이에 맞도록 데이터를 자르므로(truncate) 주의한다.
또한, 고정 길이 문자열 타입인 CHAR 에서는 선언한 길이에 고정되므로, 문자를 저장할 때 오른쪽에 공백 문자(trailing space)를 채운다. 한편, 가변 길이 문자열 타입인 VARCHAR 에서는 공백 문자를 채우지 않고 실제 입력된 문자열만큼 저장한다.
VARCHAR 타입에서 지정할 수 있는 최대 길이는 1,073,741,823이며, CHAR 타입에서 지정할 수 있는 최대 길이는 268,435,455이다.
또한, CSQL 문장으로 한 번에 입력 또는 출력할 수 있는 최대 크기는 8192KB이다.
Note
9.0 미만 버전에서 CHAR 나 VARCHAR 타입의 길이는 문자의 개수가 아닌 문자의 바이트 크기를 나타내었다.
문자셋(Character Set, charset)
문자셋(문자 집합)은 특정 문자(symbol)를 컴퓨터에 저장할 때, 어떠한 코드로 인코딩할 것인지에 대한 규칙이 정의된 집합을 의미한다. CUBRID가 사용할 문자셋은 DB 생성 시, CHARSET 소개자 또는 COLLATE 수정자 사용 시 지정될 수 있다. 문자셋에 대한 자세한 설명은 다국어 개요 을 참고한다.
문자셋의 정렬(Collating Character Set)
콜레이션(collation)은 어느 문자셋이 설정된 상태에서 데이터베이스에 저장된 값들을 검색하거나 정렬하는 작업을 위해 문자들을 서로 비교할 때 사용하는 규칙들의 집합이다. 문자셋에 대한 자세한 설명은 다국어 개요 을 참고한다.
문자열 변환(Character String Coercion)
고정길이와 가변길이 문자열 사이에는 두 문자의 길이가 비교 가능할 수 있도록 자동 변환된다. 자동 변환은 동일한 문자셋에 속하는 문자열에만 적용된다.
예를 들어, 데이터 타입이 CHAR (5)인 칼럼을 추출하여 데이터 타입이 CHAR (10)인 칼럼에 삽입하는 경우 자동으로 데이터 타입이 CHAR (10)으로 변환되어 삽입된다. 문자열을 명시적으로 변환할 수도 있는데, 이 때에는 CAST 연산자를 사용한다(
CAST()
참조).
문자열 압축(String compression)
가변 문자열 타입 값(VARCHAR(n))은 데이터베이스(힙 파일, 인덱스 파일 또는 목록 파일)에 저장하기 전에 압축할 수 있다(LZO1X 알고리즘 사용). 최소 255바이트 이상이면 압축이 시도된다(이 값은 미리 정의되어 있으며 변경할 수 없음). 압축이 효율적이지 않으면(압축 값의 크기 및 오버헤드가 압축 전의 원래 값과 동일하거나 큰 경우) 압축되지 않은 채로 값이 저장된다. 압축은 기본적으로 활성화되어 있으며 시스템 파라미터 enable_string_compression 를 설정하여 비활성화할 수 있다. 압축 오버헤드는 8바이트(압축 버퍼 크기 4바이트, 압축 해제 문자열 예상 크기 4바이트)이다. 압축된 문자열은 데이터베이스에서 읽을 때 압축이 풀어진다. 데이터 값의 압축 여부를 파악하려면 DISK_SIZE 함수 결과를 인자가 동일한 OCTET_LENGTH 함수 결과와 비교한다. DISK_SIZE 값이 더 작으면(값 오버헤드 무시) 압축이 사용되었음을 나타낸다.
CHAR(n)¶
고정길이 문자열은 CHAR (n)로 표현하며, 여기서 n 은 문자의 개수를 나타낸다. n 이 생략되면 길이는 기본값인 1로 지정된다.
문자열의 길이가 n 을 초과하면 allow_truncated_string 설정 값이 yes 인 경우 초과 부분을 절삭하지만, 설정 값이 no인경우 에러가 발생한다. n 보다 작은 문자열이 저장되면 나머지 부분은 공백 문자로 채워진다.
CHAR (n)와 CHARACTER (n)는 같은 의미로 사용된다.
Note
CUBRID 9.0 미만 버전에서는 n 이 문자의 개수가 아니라 바이트 길이를 나타낸다.
n 은 1부터 268,435,455 (256M) 사이의 정수이다.
공백 값은 빈 따옴표(‘’)로 처리하며, 이 경우 LENGTH 함수의 리턴 값은 0이 아니라 CHAR (n)에서 정의한 고정길이이다. 즉, CHAR (10)인 칼럼에 공백 값을 넣더라도 리턴 값은 10이며, n 이 생략되면 기본값이 1 이므로 CHAR (1)로 간주된다.
채우는(padding) 문자로 사용되는 공백은 특수 문자를 비롯한 어느 문자보다도 작은 것으로 간주된다.
CHAR(12)에 'pacesetter'를 저장하면 'pacesetter '가 된다(10자리 문자열과 공백 문자 2개로 구성됨).
CHAR(10)에 'pacesetter '를 저장하면 'pacesetter'가 된다(10을 넘어서는 부분이 공백 문자이므로 이를 절삭하고 10자리 문자열로 구성됨. 단, **allow_truncated_string** 설정 값이 **no**\인 경우 에러가 발생).
CHAR(4)에 'pacesetter'를 저장하면 'pace'가 된다(문자열의 크기가 4보다 크므로 절삭함. 단, **allow_truncated_string** 설정 값이 **no**\인 경우 에러가 발생).
CHAR에 'p '를 저장하면 'p'가 된다(n이 생략되면 길이는 기본값인 1로 지정됨).
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
VARCHAR(n) 또는 CHAR VARYING(n)¶
가변길이 문자열은 VARCHAR (n)로 표현하며, 여기서 n 은 문자의 개수를 나타낸다. n 이 생략되면 길이는 최대 길이인 1,073,741,823로 지정된다.
문자열의 길이가 n 을 초과하면 allow_truncated_string 설정 값이 yes인 경우 초과 부분을 절삭하지만, 설정 값이 no인경우 에러가 발생한다. n 보다 작은 문자열이 저장되면 CHAR (n)는 나머지 부분을 공백 문자로 채우지만 VARCHAR (n)에는 해당 문자열 길이만큼만 저장한다.
VARCHAR (n)와 CHARACTER VARYING (n), CHAR VARYING (n)은 같은 의미로 사용된다.
Note
CUBRID 9.0 미만 버전에서는 n 이 문자의 개수가 아니라 바이트 길이를 나타낸다.
STRING 은 VARCHAR (최대 길이)와 같다.
n 은 1부터 1,073,741,823(1G) 사이의 정수이다.
공백 값은 빈 따옴표(‘’)로 처리하며, 이 경우 LENGTH 함수의 리턴 값은 0이다.
VARCHAR(4)에 'pacesetter'를 저장하면 'pace'가 된다(문자열의 크기가 4보다 크므로 절삭함. 단, **allow_truncated_string** 설정 값이 **no**\인 경우 에러가 발생).
VARCHAR(12)에 'pacesetter'를 저장하면 'pacesetter'가 된다(10자리 문자열로 구성됨).
VARCHAR(12)에 'pacesetter '를 저장하면 'pacesetter '가 된다(10자리 문자열과 공백 문자 2개로 구성됨).
VARCHAR(10)에 'pacesetter '를 저장하면 'pacesetter'가 된다(10을 넘어서는 부분이 공백 문자이므로 이를 절삭하고 10자리 문자열로 구성됨. 단, **allow_truncated_string** 설정 값이 **no**\인 경우 에러가 발생).
VARCHAR에 'p '를 저장하면 'p '가 된다(n이 생략되면 최대 길이는 기본값인 1,073,741,823로 지정되고, 저장 시 나머지 부분은 공백 문자로 채워지지 않음).
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
STRING¶
STRING 은 가변길이 문자열 데이터 타입이다. STRING 은 VARCHAR 를 최대 길이로 지정한 것과 같다. 즉 STRING 은 VARCHAR (1,073,741,823)과 동일하다.
특수 문자 이스케이프¶
CUBRID는 특수 문자를 이스케이프(escape)하는 방법을 두 가지 지원한다. 하나는 따옴표를 이용한 방법이고, 다른 하나는 백슬래시(\)를 이용한 방법이다.
따옴표 이스케이프
cubrid.conf 의 시스템 파라미터 ansi_quotes가 no로 설정되어 있으면 문자열을 감쌀 때 큰따옴표(“)와 작은따옴표(’) 둘 다 사용할 수 있다. ansi_quotes 파라미터의 기본값은 yes 로, 문자열을 감쌀 때 작은따옴표만 사용할 수 있다.
작은따옴표로 감싼 문자열에 포함된 작은따옴표는 두 개의 작은따옴표(‘’)를 쓴다.
큰따옴표로 감싼 문자열에 포함된 큰따옴표는 두 개의 큰따옴표(“”)를 쓴다. (ansi_quotes 값이 no인 경우)
큰따옴표로 감싼 문자열에 포함된 작은따옴표는 이스케이프하지 않아도 된다. (ansi_quotes 값이 no인 경우)
작은따옴표로 감싼 문자열에 포함된 큰따옴표는 이스케이프하지 않아도 된다.
백슬래시 이스케이프
백슬래시(\)를 이용한 이스케이프는 cubrid.conf의 시스템 파라미터 no_backslash_escapes를 no로 설정했을 때에만 사용할 수 있다. no_backslash_escapes 파라미터의 기본값은 yes 이다. no_backslash_escapes의 값이 no인 경우, 다음과 같은 특수 문자를 의미한다.
\’ : 작은따옴표(‘)
\” : 큰따옴표(“)
\n : 뉴라인(newline, linefeed) 문자
\r : 캐리지 리턴(carriage return) 문자
\t : 탭(tab) 문자
\\ : 백슬래시(backslash)
\% : 퍼센트 기호(%). 자세한 내용은 아래 설명을 참고한다.
\_ : 언더바(_). 자세한 내용은 아래 설명을 참고한다.
다른 모든 이스케이프에 대해서는 백슬래시가 무시된다. 예를 들어 “x”는 그냥 “x”라고 입력한 것과 같다.
\% 와 \_ 는 LIKE 와 같은 패턴 매칭 구문에서 퍼센트 기호와 언더바를 찾을 때 쓰이며, 백슬래시가 없으면 와일드카드 문자(wildcard character)로 쓰인다. 패턴 매칭 구문 밖에서는 와일드카드 문자가 아닌 일반 문자열 “\%”와 “\_”로 그대로 쓰인다. 자세한 내용은 LIKE 을 참고한다.
다음은 cubrid.conf의 시스템 파라미터 ansi_quotes가 yes(기본값)이고 no_backslash_escapes가 no일 때 백슬래시에 대해 이스케이프를 수행한 결과이다.
-- ansi_quotes=yes, no_backslash_escapes=no
SELECT STRCMP('single quotes test('')', 'single quotes test(\')');
위의 구문을 실행하면, 백슬래시가 이스케이프 문자로 인식되므로 두 문자열은 같은 것으로 인식된다.
strcmp('single quotes test('')', 'single quotes test('')')
=============================================================
0
SELECT STRCMP('\a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z', 'a\bcdefghijklm\nopq\rs\tuvwxyz');
위의 구문을 실행하면, 백슬래시가 이스케이프 문자로 인식되므로 두 문자열은 같은 것으로 인식된다.
strcmp('abcdefghijklm
s uvwxyz', 'abcdefghijklm
s uvwxyz')
=====================================================================
0
SELECT LENGTH('\\');
위의 구문을 실행하면, 백슬래시가 이스케이프 문자로 인식되므로 문자열의 길이는 1이 된다.
char_length('\')
===================
1
다음은 cubrid.conf의 시스템 파라미터 ansi_quotes가 yes(기본값)이고 no_backslash_escapes가 yes(기본값)일 때 수행한 결과이다. 백슬래시는 일반 문자로 인식된다.
-- ansi_quotes=yes, no_backslash_escapes=yes
SELECT STRCMP('single quotes test('')', 'single quotes test(\')');
위의 구문을 실행하면, 아직 따옴표가 열린 것으로 간주하여 아래와 같은 에러가 발생한다. CSQL 인터프리터의 SQL 입력 화면에서 위의 구문을 입력하면 다음 따옴표가 입력되기를 대기한다.
ERROR: syntax error, unexpected UNTERMINATED_STRING, expecting SELECT or VALUE or VALUES or '('
SELECT STRCMP('\a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z', 'a\bcdefghijklm\nopq\rs\tuvwxyz');
위의 구문을 실행하면, 백슬래시가 일반 문자로 인식되므로 두 문자열의 비교 결과는 서로 다른 것으로 인식된다.
strcmp('\a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z', 'a\bcdefghijklm\nopq\rs\tuvwxyz')
===================================================================================================
-1
SELECT LENGTH('\\');
위의 구문을 실행하면, 백슬래시가 일반 문자로 인식되므로 문자열의 길이는 2가 된다.
char_length('\\')
====================
2
다음은 cubrid.conf의 시스템 파라미터 ansi_quotes가 yes이고 no_backslash_escapes가 no일 때 LIKE 절에 대해 이스케이프를 수행한 결과이다.
-- ansi_quotes=yes, no_backslash_escapes=no
CREATE TABLE t1 (a VARCHAR(200));
INSERT INTO t1 VALUES ('aaabbb'), ('aaa%');
SELECT a FROM t1 WHERE a LIKE 'aaa\%' ESCAPE '\\';
a
======================
'aaa%'
‘%’가 패턴 매칭 문자가 아닌 일반 문자로 인식되기 때문에, 질의를 수행하면 1개의 행만 리턴한다.
LIKE 절의 문자열에서는 백슬래시가 항상 일반 문자로 간주되기 때문에, ‘%’를 패턴 매칭 문자가 아닌 일반 문자로 인식시키려면 ESCAPE 절을 지정하여 백슬래시가 이스케이프 문자임을 명시해야 한다. ESCAPE 절에서는 백슬래시가 이스케이프 문자로 간주되기 때문에, 두 개의 백슬래시 문자를 사용했다.
위의 SELECT 질의에서 이스케이프 문자를 백슬래시가 아닌 다른 문자로 쓰려면 아래와 같이 사용할 수 있다.
SELECT a FROM t1 WHERE a LIKE 'aaa#%' ESCAPE '#';
비교 규칙¶
두 문자열 값을 비교할 때 후행 공백에 대한 비교 규칙은 다음과 같다.
후행 공백 무시
후행 공백 포함
후행 공백 무시
두 문자열 값이 모두 고정 길이 타입 (CHAR) 인 경우의 비교는 아래 예와 같이 후행 공백을 무시한다. ‘abc’와 ‘abc ‘ 비교 결과는 “일치” 이다.
후행 공백 포함
두 문자열 값이 모두 가변 길이 타입 (VARCHAR) 인 경우의 비교는 아래 예와 같이 후행 공백을 무시하지 않는다. ‘abc’를 ‘abc ‘ 비교 결과는 ‘abc ‘가 ‘abc’보다 “크다” 이다.
예외
두 문자열 값을 비교할 때 하나는 고정형이고 다른 하나는 변수형이면 CUBRID는 후행 공백 포함 규칙을 따른다.
ENUM 데이터 타입¶
ENUM 타입은 열거형 문자열 상수들의 중복 없는 순서 집합으로 구성되어 있는 타입이다. 열거형 칼럼을 생성하는 구문은 다음과 같다.
<enum_type> ::=
ENUM '(' <char_string_literal_list> ')'
<char_string_literal_list> ::=
<char_string_literal_list> ',' CHAR_STRING |
CHAR_STRING
다음은 ENUM 칼럼을 정의하는 예이다.
CREATE TABLE tbl (
color ENUM ('red', 'yellow', 'blue', 'green')
);
이 타입의 칼럼에 DEFAULT 속성이 지정될 수 있다.
색인은 원소들이 열거형 타입에 정의된 순서에 따라 각 원소에 연관되어 있다. 예를 들어, color 칼럼(NULL 값을 허용한다고 가정)은 다음 값 중 하나를 가질 수 있다.
값
색인 번호
NULL
NULL
‘red’
1
‘yellow’
2
‘blue’
3
‘green’
4
ENUM 타입 값의 집합은 512 개보다 많은 원소를 가질 수 없으며, 집합의 각 원소는 고유해야 한다. 각 ENUM 타입 값에 대해 해당 색인만 저장하기 때문에, ENUM 타입은 2 바이트의 저장 공간을 사용한다. 문자열 값이 아니라 해당 색인만 저장함으로써 저장 공간을 줄일 수 있으며 이로 인한 성능 이점도 얻을 수 있다.
ENUM 타입을 사용할 때 열거형 값과 값의 색인 둘 다 활용할 수 있다. 예를 들어, ENUM 타입 칼럼에 값을 삽입할 때 사용자는 ENUM 타입의 값 또는 색인을 사용할 수 있다.
-- insert enum element 'yellow' with index 2
INSERT INTO tbl (color) VALUES ('yellow');
-- insert enum element 'red' with index 1
INSERT INTO tbl (color) VALUES (1);
표현식에서 사용될 때 ENUM 타입은 문맥에 따라 CHAR 타입 또는 숫자로 동작한다.
-- the first result column has ENUM type, the second has INTEGER type and the third has VARCHAR type
SELECT color, color + 0, CONCAT(color, '') FROM tbl;
color color+0 concat(color, '')
=========================================================
'yellow' 2 'yellow'
'red' 1 'red'
문맥 상 CHAR나 숫자 타입이 아닌 다른 타입으로 사용될 때, 열거형은 색인 또는 열거형 값을 사용하는 해당 타입으로 변환된다. 아래 표는 타입 변환 시 ENUM 타입의 어떤 부분이 사용되는지를 보여준다.
타입
값(색인/값)
SHORT
색인
INTEGER
색인
BIGINT
색인
FLOAT
색인
DOUBLE
색인
NUMERIC
색인
TIME
값
DATE
값
DATETIME
값
TIMESTAMP
값
CHAR
값
VARCHAR
값
BIT
값
VARBIT
값
ENUM 타입 비교¶
= 또는 IN 연산자가 (<enum_칼럼> <연산자> <상수>) 형식으로 주어지면, 시스템은 상수를 ENUM 타입으로 변환하려고 한다. 변환에 실패하면 오류를 반환하지 않고 비교 결과를 FALSE로 반환하는데, 이와 같은 동작은 이러한 두 개의 연산자에 대한 인덱스 스캔 질의 계획을 허용하기 위해서이다.
다른 모든 비교 연산자에 대해 ENUM 타입은 다른 피연산자의 타입으로 변환된다. 두 개의 ENUM 타입 간에 비교 연산이 수행되면 두 피연산자 모두 CHAR 타입으로 변환되며 CHAR 타입의 규칙을 따른다. =과 IN 조건을 제외한 ENUM 칼럼을 포함한 나머지 조건은 인덱스 스캔의 고려 대상이 아니다.
이러한 규칙을 이해하기 위해 다음의 예를 살펴보자.
CREATE TABLE tbl (
color ENUM ('red', 'yellow', 'blue', 'green')
);
INSERT INTO tbl (color) VALUES (1), (2), (3), (4);
다음 질의는 상수 ‘red’를 색인 번호 1을 가진 열거형 값 ‘red’로 변환한다.
SELECT color FROM tbl WHERE color = 'red';
color
======================
'red'
SELECT color FROM tbl WHERE color = 1;
color
======================
'red'
다음 질의는 변환 오류를 반환하지는 않지만 어떠한 결과도 반환하지 않는다.
SELECT color FROM tbl WHERE color = date'2010-01-01';
SELECT color FROM tbl WHERE color = 15;
SELECT color FROM tbl WHERE color = 'asdf';
다음 질의에서 ENUM 타입은 다른 피연산자의 타입으로 변환된다.
-- CHAR comparison using the enum value
SELECT color FROM tbl WHERE color < 'pink';
color
======================
'blue'
'green'
-- INTEGER comparison using the enum index
SELECT color FROM tbl WHERE color > 3;
color
======================
'green'
-- Conversion error
SELECT color FROM tbl WHERE color > date'2012-01-01';
ERROR: Cannot coerce value of domain "enum" to domain "date".
ENUM 타입 정렬¶
ENUM 타입 값은 열거형 값이 아니라 값의 색인에 의해 정렬된다. ENUM 타입 칼럼을 정의할 때는 열거되는 값의 순서도 함께 고려해야 한다.
SELECT color FROM tbl ORDER BY color ASC;
color
======================
'red'
'yellow'
'blue'
'green'
ENUM 타입 칼럼으로 저장된 값을 CHAR 값으로 정렬하려면 열거형 값을 CHAR 타입으로 변환(CAST)하면 된다.
SELECT color FROM tbl ORDER BY CAST (color AS VARCHAR) ASC;
color
======================
'blue'
'green'
'red'
'yellow'
참고 사항¶
ENUM 타입은 재사용 가능한 타입이 아니다. 여러 개의 칼럼이 같은 ENUM 집합의 값을 요구한다 하더라도, 각각의 칼럼에 대해 ENUM 타입이 정의되어야 한다. ENUM 타입의 두 칼럼을 비교하는 경우 비록 두 ENUM 타입이 같은 집합 값을 정의했다고 하더라도, 두 칼럼이 CHAR 타입으로 변환된 것처럼 동작한다.
ALTER … CHANGE 문을 사용하여 ENUM 타입 값의 집합을 수정하려면 alter_table_change_type_strict 파라미터의 값이 반드시 yes여야 한다. 이 경우 시스템은 새로운 타입으로 변환한 열거형 값(문자열 리터럴)을 사용한다. 기존 값이 새로운 ENUM 타입 값의 집합을 벗어나면 자동으로 공백 문자열(‘’)로 매핑된다.
CREATE TABLE tbl(color ENUM ('red', 'green', 'blue'));
INSERT INTO tbl VALUES('red'), ('green'), ('blue');
다음 문장은 ENUM 타입이 ‘yellow’ 값을 가지도록 변경한다.
ALTER TABLE tbl CHANGE color color ENUM ('red', 'green', 'blue', 'yellow');
INSERT into tbl VALUES(4);
SELECT color FROM tbl;
color
======================
'red'
'green'
'blue'
'yellow'
다음의 예에서 ‘green’ 값이 새로운 ENUM 타입 정의에 매핑되지 않기 때문에, 모든 투플의 ‘green’이 ‘’로 변경된다.
ALTER TABLE tbl CHANGE color color ENUM ('red', 'yellow', 'blue');
SELECT color FROM tbl;
color
======================
'red'
''
'blue'
'yellow'
ENUM 타입은 CUBRID 드라이버에서 문자열로 매핑된다. 다음은 JDBC 응용에서 ENUM 타입을 사용하는 예이다.
Statement stmt = connection.createStatement("SELECT color FROM tbl");
ResultSet rs = stmt.executeQuery();
while(rs.next()){
System.out.println(rs.getString());
}
다음은 CCI 응용에서 ENUM 타입을 사용하는 예이다.
req_id = cci_prepare (conn, "SELECT color FROM tbl", 0, &err);
error = cci_execute (req_id, 0, 0, &err);
if (error < CCI_ER_NO_ERROR)
{
/* handle error */
}
error = cci_cursor (req_id, 1, CCI_CURSOR_CURRENT, &err);
if (error < CCI_ER_NO_ERROR)
{
/* handle error */
}
error = cci_fetch (req_id, &err);
if (error < CCI_ER_NO_ERROR)
{
/* handle error */
}
cci_get_data (req, idx, CCI_A_TYPE_STR, &data, 1);
BLOB/CLOB 데이터 타입¶
External LOB(Large Object) 타입은 텍스트 또는 이미지 등 크기가 큰 객체를 처리하기 위한 데이터 타입이다. LOB 타입 데이터가 생성 및 삽입되면 이는 외부 저장소에 파일로 저장되고 CUBRID 데이터베이스에는 해당 파일의 위치 정보(LOB locator)가 저장된다. 데이터베이스에서 해당 데이터(LOB locator)가 삭제되면, 외부 저장소에 저장된 해당 파일이 함께 삭제된다. CUBRID는 두 가지 LOB 타입을 지원한다.
Binary Large Object(BLOB)
Character Large Object(CLOB)
Note
관련 용어
LOB (Large Object): 이진 바이너리 또는 텍스트 등 크기가 큰 객체이다.
FBO (File Based Object): DB 데이터를 DB 외부의 파일로 저장하는 객체이다.
External LOB: LOB 데이터를 DB 외부에 파일로 저장하는 객체로서 FBO라고도 하며, CUBRID는 이를 지원한다. Internal LOB은 LOB 데이터를 DB 내부에 저장하는 객체이다.
External Storage: LOB을 저장하는 외부 저장소이다(예: POSIX 파일 시스템).
LOB Locator: 외부 저장소에 저장된 파일의 경로명이다.
LOB Data: LOB Locator에 명시된 위치에 있는 파일의 내용이다.
LOB 데이터는 외부 저장소에 다음과 같은 파일명으로 저장된다.
{table_name}_{unique_name}
table_name : prefix로 삽입되어 하나의 외부 저장소에 여러 테이블의 LOB 데이터를 저장할 수 있다.
unique_name : 데이터베이스 서버가 임의로 생성하는 이름이다.
LOB 데이터의 저장소는 데이터베이스 서버 상의 로컬 파일 시스템이다. LOB 데이터는 cubrid createdb 유틸리티의 -lob-base-path 옵션 값으로 지정된 경로에 저장되며, 옵션이 생략될 경우 데이터베이스 볼륨이 생성되는 [db-vol path]/lob 경로에 저장된다. 보다 자세한 내용은 createdb 및 저장소 생성 및 관리 를 참고한다.
CUBRID가 제공하는 API나 도구를 사용하지 않고 사용자가 임의로 LOB 파일 내용을 수정하면, 해당 내용의 일치성이 보장되지 않으므로 주의한다.
데이터베이스 위치 정보 파일(databases.txt)에 LOB 데이터 파일 경로가 등록되어 있음에도 불구하고 해당 경로가 삭제된 경우, 데이터베이스 서버(cub_server) 및 독립 모드(standalone)로 동작하는 유틸리티가 정상적으로 실행되지 않으므로 주의한다.
BLOB¶
바이너리 데이터를 DB 외부에 저장하기 위한 타입으로, BLOB 데이터의 최대 길이는 외부 저장소에서 생성 가능한 파일 크기이다. BLOB 타입은 SQL 문에서 비트열 타입으로 입출력 값을 표현한다. 즉, BIT (n), BIT VARYING (n) 타입과 호환되며, 명시적 타입 변환만 허용된다. 데이터 길이가 서로 다른 경우에는 최대 길이가 작은 타입에 맞추어 절삭(truncate)된다. BLOB 타입 값을 바이너리 값으로 변환하는 경우, 변환된 데이터는 최대 1GB를 넘을 수 없다. 반대로 바이너리를 BLOB 타입으로 변환하는 경우, 변환된 데이터는 BLOB 저장소에서 제공하는 최대 파일 크기를 넘을 수 없다.
CLOB¶
문자열 데이터를 DB 외부에 저장하기 위한 타입으로, CLOB 데이터의 최대 길이는 외부 저장소에서 생성 가능한 파일 크기이다. CLOB 타입은 SQL 문에서 문자열 타입으로 입출력 값을 표현한다. 즉, CHAR (n), VARCHAR (n) 타입과 호환된다. 단, 명시적 타입 변환만 허용되며, 데이터 길이가 서로 다른 경우에는 최대 길이가 작은 타입에 맞추어 절삭(truncate)된다. CLOB 타입 값을 문자열 값으로 변환하는 경우, 변환된 데이터는 최대 1GB를 넘을 수 없다. 반대로 문자열을 CLOB 타입으로 변환하는 경우, 변환된 데이터는 CLOB 저장소에서 제공하는 최대 파일 크기를 넘을 수 없다.
정의 및 변경¶
CREATE TABLE 문 또는 ALTER TABLE 문을 사용하여 BLOB / CLOB 타입 칼럼을 생성/추가/삭제할 수 있다.
LOB 타입 칼럼에 대해서는 인덱스를 생성할 수 없다.
LOB 타입 칼럼에 대해서는 PRIMARY KEY, FOREIGN KEY, UNIQUE, NOT NULL 제약 조건을 정의할 수 없다. 또한, SHARED 속성을 정의할 수 없으며, DEFAULT 속성은 NULL 값에 대해서만 정의할 수 있다.
LOB 타입 칼럼/데이터는 컬렉션 타입의 원소가 될 수 없다.
LOB 타입 칼럼이 있는 레코드를 삭제하는 경우, LOB 칼럼 값(Locator) 및 외부 저장소 내 파일을 모두 삭제한다. 또한, 기본 키 테이블에서 LOB 타입 칼럼이 있는 레코드가 삭제됨에 따라 이를 참조하는 외래 키 테이블의 레코드가 함께 삭제되는 경우, LOB 칼럼 값(Locator) 및 외부 저장소 내 LOB 파일을 모두 삭제한다. 단, ALTER TABLE … DROP 문을 사용하여 LOB 칼럼을 삭제하거나 DROP TABLE 문을 사용하여 해당 테이블을 삭제하는 경우, LOB 칼럼 값(Lob locator)만 삭제하고 LOB 칼럼이 참조하는 외부 저장소 내 LOB 파일은 삭제하지 않는다.
-- creating a table and CLOB column
CREATE TABLE doc_t (doc_id VARCHAR(64) PRIMARY KEY, content CLOB);
-- an error occurs when UNIQUE constraint is defined on CLOB column
ALTER TABLE doc_t ADD CONSTRAINT content_unique UNIQUE(content);
-- an error occurs when creating an index on CLOB column
CREATE INDEX i_doc_t_content ON doc_t (content);
-- creating a table and BLOB column
CREATE TABLE image_t (image_id VARCHAR(36) PRIMARY KEY, doc_id VARCHAR(64) NOT NULL, image BLOB);
-- an error occurs when adding a BOLB column with NOT NULL constraint
ALTER TABLE image_t ADD COLUMN thumbnail BLOB NOT NULL;
-- an error occurs when adding a BLOB column with DEFAULT attribute
ALTER TABLE image_t ADD COLUMN thumbnail2 BLOB DEFAULT BIT_TO_BLOB(X'010101');
저장 및 변경¶
BLOB / CLOB 타입 칼럼에는 각각 BLOB / CLOB 타입 값이 저장되며, 바이너리 또는 문자열 데이터를 입력하는 경우에는 각각 BIT_TO_BLOB()
, CHAR_TO_CLOB()
함수를 사용하여 명시적으로 타입을 변환을 수행하여야 한다.
INSERT 문을 사용하여 LOB 칼럼에 값을 입력하면, 내부적으로는 외부 저장소에 파일을 생성하여 해당 데이터를 저장하고, 실제 칼럼 값으로 해당 파일의 경로(Locator) 정보를 저장한다.
DELETE 문을 사용하여 LOB 칼럼이 존재하는 레코드를 삭제하면, 해당 LOB 칼럼 값이 참조하는 파일을 함께 삭제한다.
UPDATE 문을 사용하여 LOB 칼럼 값을 변경하는 경우, 새로운 값이 NULL 인지에 따라 다음과 같이 동작하면서 칼럼 값을 변경한다.
LOB 타입 칼럼 값을 NULL 이 아닌 값으로 변경하는 경우: LOB 칼럼에 이미 외부 파일을 참조하는 Locator 가 저장되어 있다면, 해당 파일을 삭제한다. 그리고 새로운 파일을 생성하여 NULL이 아닌 값을 저장한 후, LOB 칼럼 값에 새로운 파일에 대한 locator를 저장한다.
LOB 타입 칼럼 값을 NULL 로 변경하는 경우: LOB 칼럼에 이미 외부 파일을 참조하는 Locator 가 저장되어 있다면, 해당 파일을 삭제한다. 그리고 LOB 칼럼 값에 NULL을 바로 저장한다.
-- inserting data after explicit type conversion into CLOB type column
INSERT INTO doc_t (doc_id, content) VALUES ('doc-1', CHAR_TO_CLOB('This is a Dog'));
INSERT INTO doc_t (doc_id, content) VALUES ('doc-2', CHAR_TO_CLOB('This is a Cat'));
-- inserting data after explicit type conversion into BLOB type column
INSERT INTO image_t VALUES ('image-0', 'doc-0', BIT_TO_BLOB(X'000001'));
INSERT INTO image_t VALUES ('image-1', 'doc-1', BIT_TO_BLOB(X'000010'));
INSERT INTO image_t VALUES ('image-2', 'doc-2', BIT_TO_BLOB(X'000100'));
-- inserting data from a sub-query result
INSERT INTO image_t SELECT 'image-1010', 'doc-1010', image FROM image_t WHERE image_id = 'image-0';
-- updating CLOB column value to NULL
UPDATE doc_t SET content = NULL WHERE doc_id = 'doc-1';
-- updating CLOB column value
UPDATE doc_t SET content = CHAR_TO_CLOB('This is a Dog') WHERE doc_id = 'doc-1';
-- updating BLOB column value
UPDATE image_t SET image = (SELECT image FROM image_t WHERE image_id = 'image-0') WHERE image_id = 'image-1';
-- deleting BLOB column value and its referencing files
DELETE FROM image_t WHERE image_id = 'image-1010';
조회¶
LOB 타입 칼럼을 조회하면 칼럼이 참조하는 파일에 저장된 데이터를 출력한다. CAST()
연산자, CLOB_TO_CHAR()
함수, BLOB_TO_BIT()
함수를 사용하여 명시적 타입 변환을 수행할 수 있다.
CSQL에서 질의를 실행할 경우, 파일에 저장된 데이터가 아닌 칼럼 값(Locator)을 출력한다. BLOB / CLOB 칼럼이 참조하는 데이터를 출력하기 위해서는
CLOB_TO_CHAR()
함수를 사용하여 문자열로 변환해야 한다.문자열 처리 함수를 사용하기 위해서는
CLOB_TO_CHAR()
함수를 사용하여 문자열로 변환해야 한다.GROUP BY 절, ORDER BY 절에 LOB 칼럼을 명시할 수 없다.
비교 연산자, 관계 연산자, IN, NOT IN 연산자를 사용하여 LOB 칼럼을 비교할 수 없다. 단, IS NULL 조건식을 사용하여 LOB 칼럼 값(Locator)이 NULL 인지 비교할 수 있다. 즉, 칼럼 값이 NULL이면 TRUE를 반환하는데, 칼럼 값이 NULL인 경우는 LOB 데이터를 저장하는 파일이 존재하지 않는다는 의미이다.
LOB 칼럼을 생성하고 데이터를 입력한 이후 LOB 데이터 파일을 삭제하면, LOB 칼럼 값(Locator)이 유효하지 않은 파일을 참조하는 상태가 된다. 이처럼 LOB locator와 LOB 데이터 파일이 매칭되지 않는 칼럼에 대해
CLOB_TO_CHAR()
,BLOB_TO_BIT()
,CLOB_LENGTH()
,BLOB_LENGTH()
함수를 사용하면 NULL을 출력한다.
-- displaying locator value when selecting CLOB and BLOB column in CSQL interpreter
SELECT doc_t.doc_id, content, image FROM doc_t, image_t WHERE doc_t.doc_id = image_t.doc_id;
doc_id content image
==================================================================
'doc-1' file:/home1/data1/ces_658/doc_t.00001282208855807171_7329 file:/home1/data1/ces_318/image_t.00001282208855809474_7474
'doc-2' file:/home1/data1/ces_180/doc_t.00001282208854194135_5598 file:/home1/data1/ces_519/image_t.00001282208854205773_1215
2 rows selected.
-- using string functions after coercing its type by CLOB_TO_CHAR( )
SELECT CLOB_TO_CHAR(content), SUBSTRING(CLOB_TO_CHAR(content), 10) FROM doc_t;
clob_to_char(content) substring( clob_to_char(content) from 10)
============================================
'This is a Dog' ' Dog'
'This is a Cat' ' Cat'
2 rows selected.
SELECT CLOB_TO_CHAR(content) FROM doc_t WHERE CLOB_TO_CHAR(content) LIKE '%Dog%';
clob_to_char(content)
======================
'This is a Dog'
SELECT CLOB_TO_CHAR(content) FROM doc_t ORDER BY CLOB_TO_CHAR(content);
clob_to_char(content)
======================
'This is a Cat'
'This is a Dog'
SELECT * FROM doc_t WHERE content LIKE 'This%';
doc_id content
============================================
'doc-1' file:/home1/data1/ces_004/doc_t.00001366272829040346_0773
'doc-2' file:/home1/data1/ces_256/doc_t.00001366272815153996_1229
-- an error occurs when LOB column specified in ORDER BY/GROUP BY clauses
SELECT * FROM doc_t ORDER BY content;
ERROR: doc_t.content can not be an ORDER BY column
연산자와 함수¶
CAST()
연산자를 사용하여 BLOB / CLOB 타입과 바이너리 타입/문자열 타입 간 명시적 타입 변환을 수행할 수 있다. 자세한 내용은 CAST()
연산자를 참고한다.
CAST (<bit_type_column_or_value> AS { BLOB | CLOB })
CAST (<char_type_column_or_value> AS { BLOB | CLOB })
다음은 BLOB / CLOB 타입 처리 및 변환을 위해 제공하는 함수이다. 자세한 설명은 LOB 함수 절을 참고한다.
Note
” <blob_or_clob_column> IS NULL “: IS NULL 조건식을 사용하여 LOB 칼럼 값(Locator)이 NULL 인지 비교하고, NULL 이면 TRUE 를 반환한다.
저장소 생성 및 관리¶
LOB 데이터 파일은 기본적으로 데이터베이스 볼륨이 생성되는 <db-volume-path>/lob 디렉터리에 저장된다. 데이터베이스 생성 시 createdb -B
옵션을 통해서 LOB 데이터 파일을 저장할 디렉터리를 지정할 수 있다. 지정된 디렉터리가 존재하지 않으면 디렉터리 생성을 시도하며, 생성 실패 시에는 에러를 출력한다. 자세한 내용은 createdb -B
옵션을 참고한다.
# 현재 작업 디렉터리에 image_db 볼륨이 생성되고 LOB 데이터 파일이 저장된다.
% cubrid createdb image_db en_US
# 로컬 파일 시스템 내 "/home1/data1" 경로에 LOB 데이터 파일이 저장된다.
% cubrid createdb --lob-base-path="file:/home1/data1" image_db en_US
spacedb 유틸리티를 실행하여 LOB 파일이 저장되는 디렉터리를 확인할 수 있다.
% cubrid spacedb image_db
Space description for database 'image_db' with pagesize 16.0K. (log pagesize: 16.0K)
Volid Purpose total_size free_size Vol Name
0 GENERIC 512.0M 510.1M /home1/data1/image_db
Space description for temporary volumes for database 'image_db' with pagesize 16.0K.
Volid Purpose total_size free_size Vol Name
LOB space description file:/home1/data1
파일 저장소를 추가로 생성하려면 디스크 공간을 확보한 후 databases.txt 의 lob-base-path 를 증설한 디스크 위치로 변경한다. databases.txt 의 변경 내용을 반영하기 위하여 DB 서버를 재구동한다. 단, databases.txt 의 lob-base-path 를 변경하더라도 예전 저장소에 저장된 LOB 데이터는 접근 가능하다.
# You can change to a new directory from the lob-base-path of databases.txt file.
% cat $CUBRID_DATABASES/databases.txt
#db-name vol-path db-host log-path lob-base-path
image_db /home1/data1 localhost /home1/data1 file:/home1/data2
LOB 타입 칼럼의 데이터 파일에 대한 백업 및 복구는 지원하지 않으며, LOB 타입 칼럼의 메타 데이터 값(Locator)에 대해서만 백업 및 복구를 지원한다.
copydb 유틸리티를 사용하여 데이터베이스를 복사하는 경우, 관련 옵션이 지정되지 않으면 LOB 파일 디렉터리 경로가 복사되지 않으므로 추가로 databases.txt 파일을 설정해야 한다. 자세한 내용은 copydb 유틸리티의 copydb -B
및 copydb --copy-lob-path
옵션을 참고한다.
트랜잭션 지원 및 복구¶
LOB 데이터 변경에 대한 커밋/롤백을 지원한다. 즉, 트랜잭션 내에서 LOB Locator와 실제 LOB 데이터의 매핑(mapping)에 대한 유효성을 보장하고, 데이터베이스 장애 시 회복(recovery)을 지원한다. 트랜잭션 수행 도중 데이터베이스가 종료되어 해당 트랜잭션이 롤백 처리됨에 따라 LOB Locator와 LOB 데이터 간 매핑이 일치하지 않으면 에러를 출력한다. 아래의 예를 참고한다.
-- csql> ;AUTOCOMMIT OFF
CREATE TABLE doc_t (doc_id VARCHAR(64) PRIMARY KEY, content CLOB);
INSERT INTO doc_t VALUES ('doc-10', CHAR_TO_CLOB('This is content'));
COMMIT;
UPDATE doc_t SET content = CHAR_TO_CLOB('This is content 2') WHERE doc_id = 'doc-10';
ROLLBACK;
SELECT doc_id, CLOB_TO_CHAR(content) FROM doc_t WHERE doc_id = 'doc-10';
doc_id content
=========================================================
'doc-10' 'This is content'
-- csql> ;AUTOCOMMIT OFF
INSERT INTO doc_t VALUES ('doc-11', CHAR_TO_CLOB ('This is content'));
COMMIT;
UPDATE doc_t SET content = CHAR_TO_CLOB('This is content 3') WHERE doc_id = 'doc-11';
-- system crash occurred and then restart server
SELECT doc_id, CLOB_TO_CHAR(content) FROM doc_t WHERE doc_id = 'doc-11';
-- Error : LOB Locator references to the previous LOB data because only LOB Locator is rollbacked.
Note
JDBC와 같은 드라이버를 통해 애플리케이션에서 LOB 데이터를 조회하는 경우, JDBC는 데이터베이스 서버로부터 ResultSet을 가져온 후 Resultset에 대해 커서(cursor) 위치를 변경하면서 레코드를 인출할 수 있다. 즉, ResultSet을 가져온 시점에는 LOB 칼럼의 메타 데이터인 Locator만 저장되어 있고, 레코드를 인출하는 시점에 Locator가 참조하는 파일로부터 LOB 데이터가 실제로 인출된다. 따라서, 두 시점 사이에 LOB 데이터가 업데이트되는 경우, LOB Locator와 실제 LOB 데이터의 매핑(mapping)이 유효하지 않아 에러가 발생할 수 있다.
LOB 타입 칼럼의 메타 데이터(Locator)에 대해서만 백업/복구를 지원한다. 따라서, 장애가 발생해서 특정 시점으로 복구할 때 LOB Locator와 LOB 데이터의 매핑이 유효하지 않아 에러가 발생할 수 있다.
LOB 데이터를 다른 장비에 INSERT 하려면 반드시 LOB 칼럼 메타 데이터(Locator)가 참조하는 LOB 데이터를 읽어서 INSERT 해야 한다.
CUBRID HA에서 LOB 칼럼 메타 데이터(Locator)는 복제되고, LOB 데이터는 복제되지 않는다. 따라서 LOB 타입 저장소가 로컬에 위치할 경우, 슬레이브 노드 또는 failover 이후 마스터 노드에서 해당 칼럼에 대한 작업을 허용하지 않는다.
Warning
CUBRID 2008 R3.0 이하 버전에서는 glo (Generalized Large Object) 클래스를 사용하여 Large Object를 처리했으나, CUBRID 2008 R3.1 버전부터는 glo 클래스를 제거하고 BLOB / CLOB 데이터 타입을 지원한다. 따라서, 2008 R3.0 미만 버전의 glo 클래스를 사용하는 환경에서는 CUBRID 버전 업그레이드를 수행할 때 DB 스키마 및 애플리케이션을 수정해야 한다.
컬렉션 데이터 타입¶
여러 개의 데이터 값을 하나의 속성에 저장할 수 있도록 하는 컬렉션 데이터 타입은 관계형 데이터베이스의 확장된 기능이다. 컬렉션의 각 원소는 하나의 데이터 타입이어야 하며, 테이블(단, 뷰는 제외) 타입이 될 수도 있다. BLOB, CLOB 타입을 제외한 나머지 타입들은 컬렉션 타입의 원소가 될 수 있다.
타입 |
설명 |
타입 정의 |
입력 데이터 |
저장 데이터 |
---|---|---|---|---|
SET |
중복을 허용하지 않는 합집합 |
col_name SET VARCHAR(20) 또는 col_name SET (VARCHAR(20)) |
{‘c’,’c’,’c’,’b’,’b’,’a’} |
{‘a’,’b’,’c’} |
MULTISET |
중복을 허용하는 합집합 |
col_name MULTISET VARCHAR(20) 또는 col_name MULTISET (VARCHAR(20)) |
{‘c’,’c’,’c’,’b’,’b’,’a’} |
{‘a’,’b’,’b’,’c’,’c’,’c’} |
LIST 또는 SEQUENCE |
중복을 허용하고, 데이터 입력 순서대로 저장하는 합집합 |
col_name LIST VARCHAR(20) 또는 col_name LIST (VARCHAR(20)) |
{‘c’,’c’,’c’,’b’,’b’,’a’} |
{‘c’,’c’,’c’,’b’,’b’,’a’} |
위의 표와 같이, 컬렉션 타입으로 지정되는 값은 중괄호(‘{’, ‘}’) 안에 각 값들을 쉼표(,)로 구분하여 나열할 수 있다.
컬렉션 타입은 지정된 타입이 같다면 CAST 연산자를 이용하여 명시적으로 타입 변환이 가능하다. 아래 표는 명시적 변환이 가능한 컬렉션 타입에 관한 것이다.
FROM \ TO
SET
MULTISET
LIST
SET
-
Yes
Yes
MULTISET
Yes
-
No
LIST
Yes
Yes
-
컬렉션 타입은 콜레이션을 지원하지 않는다. 따라서 다음과 같은 질의는 오류를 반환한다.
CREATE TABLE tbl (str SET (string) COLLATE utf8_en_ci);
Syntax error: unexpected 'COLLATE', expecting ',' or ')'
SET¶
SET 는 각 원소가 서로 다른 값을 갖는 집합이다. SET 의 원소는 하나의 데이터 타입을 가져야 하고, 다른 테이블의 레코드를 가질 수도 있다.
CREATE TABLE set_tbl (col_1 SET (CHAR(1)));
INSERT INTO set_tbl VALUES ({'c','c','c','b','b','a'});
INSERT INTO set_tbl VALUES ({NULL});
INSERT INTO set_tbl VALUES ({''});
SELECT * FROM set_tbl;
col_1
======================
{'a', 'b', 'c'}
{NULL}
{' '}
SELECT CAST (col_1 AS MULTISET), CAST (col_1 AS LIST) FROM set_tbl;
cast(col_1 as multiset) cast(col_1 as sequence)
============================================
{'a', 'b', 'c'} {'a', 'b', 'c'}
{NULL} {NULL}
{' '} {' '}
INSERT INTO set_tbl VALUES ('');
ERROR: Casting '' to type set is not supported.
MULTISET¶
MULTISET 는 중복이 허용되는 집합이다. MULTISET 의 원소는 하나의 데이터 타입을 가져야 하고, 다른 테이블의 레코드를 가질 수도 있다.
CREATE TABLE multiset_tbl (col_1 MULTISET (CHAR(1)));
INSERT INTO multiset_tbl VALUES ({'c','c','c','b','b', 'a'});
SELECT * FROM multiset_tbl;
col_1
======================
{'a', 'b', 'b', 'c', 'c', 'c'}
SELECT CAST(col_1 AS SET), CAST(col_1 AS LIST) FROM multiset_tbl;
cast(col_1 as set) cast(col_1 as sequence)
============================================
{'a', 'b', 'c'} {'c', 'c', 'c', 'b', 'b', 'a'}
LIST 또는 SEQUENCE¶
LIST (SEQUENCE) 는 원소가 입력된 순서가 유지되며, 중복이 허용되는 집합이다. LIST 의 원소는 하나의 데이터 타입을 가져야 하고, 다른 테이블의 레코드를 가질 수도 있다.
CREATE TABLE list_tbl (col_1 LIST (CHAR(1)));
INSERT INTO list_tbl VALUES ({'c','c','c','b','b', 'a'});
SELECT * FROM list_tbl;
col_1
======================
{'c', 'c', 'c', 'b', 'b', 'a'}
SELECT CAST(col_1 AS SET), CAST(col_1 AS MULTISET) FROM list_tbl;
cast(col_1 as set) cast(col_1 as multiset)
============================================
{'a', 'b', 'c'} {'a', 'b', 'b', 'c', 'c', 'c'}
JSON 데이터 타입¶
CUBRID 10.2는 RFC 7159 에서 정의된 native JSON 데이터 타입을 지원한다. JSON 데이터 타입은 JSON 데이터에 대해 자동 검증을 제공하며, 빠른 액세스와 동작이 가능하다.
Note
10.2 서버에 연결하는 그 이전 버전의 드라이버는 JSON 타입 컬럼을 Varchar 타입으로 인식한다.
JSON 데이터 생성¶
JSON 포맷의 문자열 형식이 JSON 데이터 타입 컬럼에 입력되면 JSON 값으로 자동으로 변환된다.
-- 문자열을 JSON 타입 컬럼에 입력
CREATE TABLE t (id int, j JSON);
INSERT INTO t VALUES (1, '{"a":1}');
SELECT j, TYPEOF(j) FROM t;
j typeof(j)
============================================
{"a":1} 'json'
CAST 를 사용하거나 문자열 앞에 json 키워드를 사용하여 강제로 JSON으로 변환 할 수도 있다.
-- 문자열을 json으로 cast
SELECT CAST('{"a":1}' as JSON);
cast('{"a":1}' as json)
======================
{"a":1}
-- json 키워드 사용
SELECT json'{"a":1}', TYPEOF (json'{"a":1}');
json '{"a":1}' typeof(json '{"a":1}')
============================================
{"a":1} 'json'
JSON 데이터 타입은 JSON_OBJECT 나 JSON_ARRAY 를 사용하여 생성할 수도 있다.
JSON 유효성 검사¶
JSON 데이터로의 변환은 내장된 유효성 검사를 수행하고 유효한 JSON 문자열이 아닌 경우 오류를 반환한다.
-- 따옴표가 없는 문자열은 유효한 json이 아니다
SELECT json'abc';
In line 1, column 8,
에러: before ' ; '
유효하지 않은 JSON: 'abc'.
더 엄격한 유효성 검사 규칙을 가진 JSON 타입 컬럼은 JSON 스키마 표준 초안 (draft JSON Schema standard) 를 사용하여 정의할 수 있다. 만약 JSON 스키마를 다루어본 적이 없다면 JSON 스키마의 이해 (Understanding JSON Schema) 를 참고하면 된다.
다음은 스키마 사용 방법에 대한 간단한 예제이다.:
-- j 컬럼이 JSON의 문자열 타입만을 입력할 수 있도록 설정
CREATE TABLE t (id int, j JSON ('{"type": "string"}'));
-- JSON 스키마에 유효한 문자열 타입 JSON 입력
INSERT into t values (1, '"abc"');
1 개의 명령어가 실행되었습니다.
-- JSON 스키마에 유효하지 않은 문자열 타입 JSON 입력
INSERT into t values (2, '{"a":1}');
에러: before ' ); '
주어진 JSON 은 JSON schema에 대해 유효하지 않습니다. (스키마 경로: #, 키워드: type, JSON 경로: #)
JSON 데이터의 타입¶
JSON 데이터의 값은 RFC 7159 <https://tools.ietf.org/html/rfc7159#section-3> 에서 정의된 것과 같이 객체 (Object), 배열 (Array) 또는 스칼라 (Scalar) 여야 한다. 스칼라 값은 문자열, 숫자형, 불리언 (boolean) 또는 널 (null) 이다.
JSON 데이터 타입 표:
타입 |
CUBRID JSON 타입 |
설명 |
|
---|---|---|---|
Object |
JSON_OBJECT |
키-값 쌍의 집합 |
|
Array |
JSON_ARRAY |
JSON 데이터 값의 배열 |
|
Scalar |
String |
STRING |
따옴표로 묶인 문자열 |
Number |
INTEGER |
32비트의 부호 있는(signed) 숫자 |
|
BIGINT |
64비트의 부호 있는(signed) 숫자 |
||
DOUBLE |
정수가 아닌 숫자 또는 263- 1 보다 큰 정수 |
||
true |
BOOLEAN |
True 불리언 (boolean) 값 |
|
false |
BOOLEAN |
False 불리언 (boolean) 값 |
|
null |
JSON_NULL |
Null 값 |
JSON 값의 CUBRID JSON 타입은 JSON_TYPE 함수로 가져올 수 있다.
JSON 데이터 변환¶
JSON 데이터 타입은 명시적 또는 암시적으로 다른 타입으로부터 변환하여 얻을 수 있다.
JSON 데이터값을 다른 JSON 타입으로 변환하는 것은 변환하려는 타입이 스키마를 가지고 있고 변환된 값이 스키마 유효성 검사를 통과하지 못하는 경우 실패할 수 있다.
다른 타입에서 JSON으로의 변환은 다음 표에서 설명한다:
기존 타입 |
CUBRID JSON 타입 |
---|---|
Any string |
문자열은 모든 타입의 JSON 데이터로 변환할 수 있다. Note 만약 문자열의 문자셋이 UTF8이 아니라면 문자열을 먼저 UTF8로 변환한 후 JSON 데이터로 변환한다. |
Short, Integer |
INTEGER |
Bigint |
BIGINT |
Float, Double |
DOUBLE |
Numeric |
DOUBLE |
JSON 데이터 타입에서 다른 타입으로의 변환은 다음 표에서 설명한다.:
CUBRID JSON 타입 |
허용되는 다른 타입 |
---|---|
JSON_OBJECT |
JSON 데이터 값을 출력한 문자열 |
JSON_ARRAY |
JSON 데이터 값을 출력한 문자열 |
STRING |
문자열로부터 변환할 수 있는 모든 타입 |
INTEGER |
숫자값으로부터 변환할 수 있는 모든 타입 |
BIGINT |
Bigint 값으로부터 변환할 수 있는 모든 타입 |
DOUBLE |
Double 값으로부터 변환할 수 있는 모든 타입 |
BOOLEAN |
문자열로 변환된다면 “true” 또는 “false” |
숫자형으로 변환된다면 0 또는 1 |
|
JSON_NULL |
JSON ‘null’을 출력한 문자열 |
JSON 경로¶
JSON 경로는 JSON 내에서 json 요소를 참조할 수 있는 방법이다. 많은 JSON 함수는 JSON 내부에서 동작 위치를 정의하기 위해 JSON 경로 또는 JSON 포인터 인수를 필요로 한다. JSON 경로는 항상 ‘$’로 시작하며 배열 인덱스, 객체 키 토큰 및 와일드카드가 뒤따를 수 있다. 만약 ‘$’ 뒤에 다른 토큰이 없으면 경로는 JSON 데이터 루트를 가리킨다.
<json_path>::=
<start_token> [<path_token>] ...
<start_token>::=
$
<path_token>::=
<array_access_token> | <object_key_access_token> | <wildcard_token>
<array_access_token>::=
[idx]
<object_key_access_token>::=
.[key_identifier | "key_str"]
<wildcard_token>::=
.*|[*]|**path_token
예를 들어, ‘{“a”:[0,1,2,{“b”:5}]}’에 대해 ‘$.a[3].b’의 의미는 “루트의 ‘a’를 가진 멤버의 인덱스 3에 해당하는 요소의 키 ‘b’를 가진 멤버”이며 JSON 값 ‘5’를 가리킨다;
object_key_access_tokens를 키 문자열로 사용하여 동일한 key_identifiers를 표현할 수 있으며 이스케이프 문자를 사용할 수도 있다. 예: ‘$”"’은 큰따옴표를 가진 멤버를 키로 참조하는 데 사용할 수 있다.
JSON 와일드카드는 다음 세 가지 유형 중 하나가 될 수 있다.
.* , 와일드카드와 매칭되는 객체 멤버
[*], 와일드카드와 매칭되는 배열 인덱스
**, 객체 키의 시퀀스 배열 인덱스를 매칭. ** 와일드카드는 토큰(path_token)을 뒤에 붙여야 한다.
JSON 포인터 및 JSON 텍스트와 같은 경로 식은 ASCII 또는 UTF-8 문자셋으로 인코딩 되어야 한다. 만약 다른 문자셋이 사용된다면, UTF-8으로 변환(coercion)될 것이다.
JSON 포인터¶
https://tools.ietf.org/html/rfc6901에서 정의한 JSON 포인터는 JSON 경로와 다른 방법을 제공한다. JSON 포인터는 JSON 경로 및 JSON 텍스트와 동일하게 ASCII 또는 UTF-8 문자셋으로 인코딩 되어야 한다. 만약 다른 문자셋이 사용된다면, UTF-8으로 변환(coercion)될 것이다.
<json_pointer>::=
[/path_token] ... [/-]
'$.a[10].bb' 는 '/a/10/bb' 와 동일하다
'$' 는 '' 와 동일하다
특수 문자 ‘-‘는 마지막 path_token으로만 사용할 수 있으며 json_array의 끝부분을 가리키는 데 사용할 수 있다.
JSON 포인터는 비와일드카드 JSON 경로가 가리키는 것과 동일한 경로를 가리키는데 사용할 수 있다.
묵시적 타입 변환¶
표현식 내에서 타입을 변환해야 할 때 자동으로 해당 타입으로 변환하는 것을 묵시적 타입 변환(implicit type conversion)이라고 한다.
SET, MULTISET, LIST, SEQUENCE 는 명시적으로 변환되어야 한다.
DATETIME 및 TIMESTAMP 타입(타임존이 있는 타입 포함)을 DATE 타입 또는 TIME 타입으로 변환하면 데이터 손실이 발생한다. DATE 타입을 DATETIME 타입 또는 TIMESTAMP 타입(타임존이 있는 타입 포함)으로 변환하면 시간이 ‘12:00:00 AM’으로 설정된다.
타임존 타입 값에서 타임존 부분은 참조용일 뿐이며, 정확한 값은 UTC 참조에 저장된다. 타임존이 있는 타입에서 타임존이 없는 타입으로 값을 변환하면 세션 타임존을 사용한 것처럼 변환된다. 타임존이 없는 타입에서 타임존이 있는 타입으로 값을 변환하면 세션 타임존을 고려하여 변환한다. 타임존 타입과 관련한 값 변환에 대한 자세한 내용은 날짜/시간 데이터 타입 을 참고한다.
문자열 타입이나 정확한 수치형 타입을 부동소수점 수치형 타입으로 변환하면 값이 정확하지 않을 수 있다. 문자열 타입과 정확한 수치형 타입은 값을 표현하기 위해 십진 정밀도(decimal precision)를 사용하지만 부동소수점 수치형 타입은 이진 정밀도(binary precision)를 사용하기 때문이다.
CUBRID가 수행하는 묵시적 타입 변환은 다음과 같다.
묵시적 타입 변환 표 1
From \ To
DATETIME
DATETIMELTZ
DATETIMETZ
DATE
TIME
TIMESTAMP
TIMESTAMPLTZ
TIMESTAMPTZ
DATETIME
-
O
O
O
O
O
O
O
DATETIMELTZ
O
-
O
O
O
O
O
O
DATETIMETZ
O
O
-
O
O
O
O
O
DATE
O
O
O
-
O
O
O
TIME
-
TIMESTAMP
O
O
O
O
O
-
O
O
TIMESTAMPLTZ
O
O
O
O
O
O
-
O
TIMESTAMPTZ
O
O
O
O
O
O
O
-
DOUBLE
O
O
O
O
FLOAT
O
O
O
O
NUMERIC
O
O
O
BIGINT
O
O
O
O
INT
O
O
O
O
SHORT
O
O
O
O
BIT
VARBIT
CHAR
O
O
O
O
O
O
O
O
VARCHAR
O
O
O
O
O
O
O
O
숫자 값이 TIME 또는 TIMESTAMP(TIMESTAMPLTZ, TIMESTAMPTZ)로 변경될 때의 제약 사항
NUMERIC 타입을 제외한 모든 숫자 타입은 TIME 타입으로 변환될 수 있으며, 이때 TIME은 입력 숫자를 86,400초(1일)로 나눈 나머지 값을 초로 계산한 값이다.
NUMERIC**을 포함한 모든 숫자 타입은 **TIMESTAMP, TIMESTAMPLTZ, TIMESTAMPTZ 타입으로 변환될 수 있으며, 이때 입력 숫자는 최대 2,147,483,647을 초과할 수 없다.
묵시적 타입 변환 표 2
From \ To
INT
SHORT
BIT
VARBIT
CHAR
VARCHAR
DOUBLE
FLOAT
NUMERIC
BIGINT
DATETIME
O
O
DATETIMELTZ
O
O
DATETIMETZ
O
O
DATE
O
O
TIME
O
O
TIMESTAMP
O
O
TIMESTAMPLTZ
O
O
TIMESTAMPTZ
O
O
DOUBLE
O
O
O
O
-
O
O
O
FLOAT
O
O
O
O
O
-
O
O
NUMERIC
O
O
O
O
O
O
-
O
BIGINT
O
O
O
O
O
O
O
-
INT
-
O
O
O
O
O
O
O
SHORT
O
-
O
O
O
O
O
O
BIT
-
O
O
O
VARBIT
O
-
O
O
CHAR
O
O
O
O
-
O
O
O
O
O
VARCHAR
O
O
O
O
O
-
O
O
O
O
변환 규칙¶
INSERT와 UPDATE¶
영향을 받는 칼럼의 타입으로 값의 타입이 변환된다.
CREATE TABLE t(i INT);
INSERT INTO t VALUES('123');
SELECT * FROM t;
i
=============
123
함수¶
함수에 입력한 인자 값을 함수에서 지정한 타입으로 변환할 수 있으면 인자의 타입이 변환된다. 아래 함수에서 기대하는 입력 인자는 숫자이므로, 문자열을 숫자로 변환한다.
SELECT MOD('123','2');
mod('123', '2')
==========================
1.000000000000000e+00
함수는 인자로 여러 타입의 값을 입력받을 수 있는데, 함수에서 지정하지 않은 타입의 값이 전달되면 다음의 우선순위에 따라 타입이 변환된다.
날짜/시간 타입 ( DATETIME > TIMESTAMP > DATE > TIME )
근사치 수치형 타입 ( DOUBLE > FLOAT )
정확한 수치형 타입 ( NUMERIC > BIGINT > INT > SHORT )
문자열 타입 ( CHAR > VARCHAR )
비교 연산¶
다음은 비교 연산자의 피연산자 타입에 따른 변환 규칙이다.
피연산자1 타입 |
피연산자2 타입 |
변환 |
비교 타입 |
---|---|---|---|
수치형 타입 |
수치형 타입 |
없음 |
NUMERIC |
문자열 타입 |
피연산자2를 DOUBLE 로 변환 |
NUMERIC |
|
날짜/시간 타입 |
피연산자1을 날짜/시간으로 변환 |
TIME/TIMESTAMP |
|
문자열 타입 |
수치형 타입 |
피연산자1을 DOUBLE 로 변환 |
NUMERIC |
문자열 타입 |
없음 |
문자열 |
|
날짜/시간 타입 |
피연산자1을 날짜/시간 타입으로 변환 |
날짜/시간 |
|
날짜/시간 타입 |
수치형 타입 |
피연산자2를 날짜/시간으로 변환 |
TIME/TIMESTAMP |
문자열 타입 |
피연산자2를 날짜/시간 타입으로 변환 |
날짜/시간 |
|
날짜/시간 타입 |
우선순위가 높은 타입으로 변환 |
날짜/시간 |
날짜/시간 타입과 수치형 타입이 비교되는 경우 위 표의 숫자가 TIME 또는 TIMESTAMP로 변환될 때 제약 조건을 참고한다.
피연산자1이 문자열 타입의 칼럼이고 피연산자2가 값인 경우, 다음과 같은 예외가 있다.
피연산자1 타입 |
피연산자2 타입 |
변환 |
비교 |
---|---|---|---|
문자열 타입의 칼럼 |
수치형 타입 값 |
피연산자2를 문자열 타입으로 변환 |
문자열 |
날짜/시간 타입 값 |
피연산자2를 문자열 타입으로 변환 |
문자열 |
피연산자2가 집합인 연산자( IS IN, IS NOT IN, = ALL, = ANY, < ALL, < ANY, <= ALL, <= ANY, >= ALL, >= ANY )에 대해서는 위의 예외가 적용되지 않는다.
다음은 비교 연산에서 묵시적 타입 변환의 예이다.
수치형 타입과 문자열 타입 피연산자
문자열 타입 피연산자가 DOUBLE 로 변환된다.
CREATE TABLE t1(i INT, s STRING); INSERT INTO t1 VALUES(1,'1'),(2,'2'),(3,'3'),(4,'4'), (12,'12'); SELECT i FROM t1 WHERE i < '11.3';
i ============= 1 2 3 4
SELECT ('2' <= 11);
('2'<=11) ============= 1
문자열 타입과 날짜/시간 타입 피연산자
문자열 타입 피연산자가 날짜/시간 타입으로 변환된다.
SELECT ('2010-01-01' < date'2010-02-02');
('2010-01-01'<date '2010-02-02') ================================== 1
SELECT (date'2010-02-02' >= '2010-01-01');
(date '2010-02-02'>='2010-01-01') =================================== 1
문자열 타입과 수치형 타입 호스트 변수 피연산자
수치형 타입 호스트 변수가 문자열 타입으로 변환된다.
PREPARE s FROM 'SELECT s FROM t1 WHERE s < ?'; EXECUTE s USING 11;
s =================== '1'
문자열 타입 칼럼과 수치형 타입 값 피연산자
수치형 타입 값이 문자열 타입으로 변환된다.
SELECT s FROM t1 WHERE s > 11;
s ================== '2' '3' '4' '12'
SELECT s FROM t1 WHERE s BETWEEN 11 AND 33;
s ====================== '2' '3' '12'
문자열 타입 칼럼과 날짜/시간 타입 값 피연산자
날짜/시간 타입 값이 문자열 타입으로 변환된다.
CREATE TABLE t2 (s STRING); INSERT INTO t2 VALUES ('01/01/1998'), ('01/01/1999'), ('01/01/2000'); SELECT s FROM t2;
s ====================== '01/01/1998' '01/01/1999' '01/01/2000'
SELECT s FROM t2 WHERE s <= date'02/02/1998';
위의 질의에서 date’02/02/1998’이 문자열 ‘02/02/1998’으로 변환되어 문자열 간의 비교 연산이 수행된다.
s ====================== '01/01/1998' '01/01/1999' '01/01/2000'
범위 연산¶
수치형 타입과 문자열 타입 피연산자
문자열 타입 피연산자가 DOUBLE 로 변환된다.
CREATE TABLE t3 (i INT); INSERT INTO t3 VALUES (1), (2), (3), (4); SELECT i FROM t3 WHERE i <= ALL {'11','12'};
i ============= 1 2 3 4
문자열 타입과 날짜/시간 타입 피연산자
문자열 타입 피연산자가 날짜/시간 타입으로 변환된다.
SELECT s FROM t2;
s ================= '01/01/1998' '01/01/1999' '01/01/2000'
SELECT s FROM t2 WHERE s <= ALL {date'02/02/1998',date'01/01/2000'};
s ================ '01/01/1998'
해당 타입으로 변환할 수 없으면 오류를 반환한다.
산술 연산¶
날짜/시간 타입 피연산자
날짜/시간 타입의 피연산자가 ‘-’ 연산자에 주어지고 타입이 서로 다르면, 두 타입을 비교하여 우선순위가 높은 쪽의 타입으로 변환된다. 다음 예는 왼쪽 피연산자의 데이터 타입이 DATE 에서 DATETIME 으로 바뀌어 결과는 DATETIME 의 ‘-’ 연산 결과인 밀리초를 출력한다.
SELECT date'2002-01-01' - datetime'2001-02-02 12:00:00 am';
date '2002-01-01'- datetime '2001-02-02 12:00:00 am' ===================================================== 28771200000
수치형 타입 피연산자
수치형 타입의 피연산자가 주어지고 타입이 서로 다르면, 두 타입을 비교하여 우선순위가 높은 쪽의 타입으로 변환된다.
날짜/시간 타입과 수치형 타입 피연산자
날짜/시간 타입과 수치형 타입의 피연산자가 ‘+’ 또는 ‘-’ 연산자에 주어지면, 수치형 타입 피연산자는 BIGINT, INT, SHORT 중 하나로 변환된다.
날짜/시간 타입과 문자열 타입 피연산자
날짜/시간 타입과 문자열 타입이 피연산자이면, ‘+’와 ‘-’ 연산자만 허용한다. ‘+’ 연산자가 사용되면 다음 규칙이 적용된다.
문자열 타입은 인터벌(interval) 값을 지닌 BIGINT 로 변환된다. 인터벌은 날짜/시간 타입 피연산자의 가장 작은 단위를 의미하며, 각 타입의 인터벌 값은 다음과 같다.
DATE : 일수(days)
TIME, TIMESTAMP : 초수(seconds)
DATETIME : 밀리초수(milliseconds)
부동소수점수는 반올림된다.
결과 타입은 날짜/시간 타입 피연산자의 타입이다.
SELECT date'2002-01-01' + '10';
date '2002-01-01'+'10' ====================== 01/11/2002
날짜/시간 타입과 문자열 타입이 피연산자이고, ‘-’ 연산자가 사용되면 다음 규칙이 적용된다.
날짜/시간 타입 피연산자가 DATE, DATETIME, TIMESTAMP 이면 문자열은 DATETIME 으로 변환되고, 날짜/시간 타입 피연산자가 TIME 이면 문자열은 TIME 으로 변환된다.
결과 타입은 항상 BIGINT 이다.
SELECT date'2002-01-01'-'2001-01-01';
date '2002-01-01'-'2001-01-01' ================================ 31536000000 -- this causes an error
SELECT date'2002-01-01'-'10';
ERROR: Cannot coerce '10' to type datetime.
수치형 타입과 문자열 타입 피연산자
수치형 타입과 문자열 타입이 피연산자이면 다음 규칙이 적용된다.
문자열은 가능하면 DOUBLE로 변환된다.
결과 타입은 DOUBLE이다.
SELECT 4 + '5.2';
4+'5.2' ========================== 9.199999999999999e+00
CUBRID 2008 R3.1 이하 버전과 달리, 날짜/시간 형태의 문자열, 즉 ‘2010-09-15’와 같은 문자열은 날짜/시간 타입으로 변환되지 않는다. 날짜/시간 타입을 갖는 리터럴 DATE’2010-09-15’ 은 덧셈, 뺄셈 연산에 사용할 수 있다.
SELECT '2002-01-01'+1;
ERROR: Cannot coerce '2002-01-01' to type double.
SELECT date'2002-01-01'+1;
date '2002-01-01'+1 ===================== 01/02/2002
문자열 타입 피연산자
두 문자열을 곱하거나 나누거나 빼면 숫자로 변환되며, 결과로 DOUBLE 타입의 값을 반환한다.
SELECT '3'*'2';
'3'*'2' ============================ 6.000000000000000e+00
‘+’ 연산자의 동작은 cubrid.conf 의 시스템 파라미터인 plus_as_concat을 어떻게 설정하느냐에 따라 결정된다. 자세한 내용은 구문/타입 관련 파라미터를 참고한다.
plus_as_concat 값이 yes(기본값)이면 두 개의 문자열을 연결한 값을 반환한다.
SELECT '1'+'1';
'1'+'1' ====================== '11'
plus_as_concat 값이 no이고 두 개의 문자열이 숫자로 변환 가능하면, 두 숫자를 더하여 DOUBLE 타입의 값을 반환한다.
SELECT '1'+'1';
'1'+'1' ========================== 2.000000000000000e+00
해당 타입으로 변환할 수 없으면 오류를 반환한다.