Character Datatypes
NLS parameters (V$NLS_PARAMETERS)
- NLS_LENGTH_SEMANTICS
- BYTE (default)
- CHAR
- NLS_CHARACTERSET
Character encoding of CHAR, VARCHAR2 and CLOB datatypes
eg: AL32UTF8 (UTF8 not recommended)- Latin characters -> 1 byte
- Chinese characters(in BMP) -> 3 bytes
- NLS_NCHAR_CHARACTERSET
Character encoding of NCHAR, NVARCHAR2 and NCLOB datatypes
eg: AL16UTF16 (UTF8 not recommended)- Latin characters -> 2 bytes
- Chinese characters(in BMP) -> 2 bytes
Char
Store character data encoded by NLS_CHARACTERSET
Char(2000 byte)
We can store up to 666 Chinese characters(666 * 3 = 1998 bytes) and 2 Latin characters(2 * 1 = 2 bytes).-
Char(n char)
We can store n chars as long as the length of encoded chars <= 2000 bytes- 0 < n <= 666
We can store n(bytes = 3*n <= 1998) Chinese chars. - 666 < n <= 2000
You can't store n(bytes = 3*n > 2000) Chinese chars.
- 0 < n <= 666
VarChar2
Store character data encoded by NLS_CHARACTERSET
-
MAX_STRING_SIZE
- STANDARD 4000 bytes
- EXTENDED 32767 bytes
VarChar2(4000 byte)
We can store up to 1333 Chinese characters(1333 * 3 = 3999 bytes) and 1 Latin characters(1 * 1 = 1 bytes).-
VarChar2(n char)
We can store n chars as long as the length of encoded chars <= 4000 bytes- 0 < n <= 1333
We can store n(bytes = 3*n <= 3999) Chinese chars. - 1333 < n <= 4000
You can't store n(bytes = 3*n > 2000) Chinese chars.
- 0 < n <= 1333
NChar
- Store unicode character data encoded by NLS_NCHAR_CHARACTERSET
For a Unicode Standard-enabled database(NLS_CHARACTERSET is set to AL32UTF8), we can also use datatype char to store unicode character data. NChar is NOT the preferred option to store unicode character data.
NVarChar2
- Store unicode character data encoded by NLS_NCHAR_CHARACTERSET
- MAX_STRING_SIZE
- STANDARD 4000 bytes
- EXTENDED 32767 bytes
For a Unicode Standard-enabled database(NLS_CHARACTERSET is set to AL32UTF8), we can also use datatype VarChar2 to store unicode character data. NVarChar is NOT the preferred option to store unicode character data.
Internal Storage
We can use dump function to inspect how data is stored.
Sample output Typ=96 Len=5: 230,177,137,49,32
Typ=96 represent data type is Char
Len=5 represent data is stored by 5 bytes
'230,177,137,49,32' represent the actual data
DROP TABLE zz_char;
CREATE TABLE zz_char (
char_b_1 CHAR(5 BYTE),
varchar2_b_1 VARCHAR2(4000 BYTE),
nchar_1 NCHAR(5),
nvarchar2_1 NVARCHAR2(2000)
);
INSERT INTO zz_char (
char_b_1,
varchar2_b_1,
nchar_1,
nvarchar2_1
) VALUES (
'汉1',
'汉2',
'字3',
'字4'
);
SELECT char_b_1, dump(char_b_1),
varchar2_b_1, dump(varchar2_b_1),
nchar_1, dump(nchar_1),
nvarchar2_1, dump(nvarchar2_1)
FROM zz_char;
Datatype | Characters | Encoding | Dump |
---|---|---|---|
char(5 byte) | 汉1 | AL32UTF8 | Typ=96 Len=5: 230,177,137,49,32 |
varchar2(4000 byte) | 汉2 | AL32UTF8 | Typ=1 Len=4: 230,177,137,50 |
nchar(5) | 字3 | AL16UTF16 | Typ=96 Len=10: 91,87,0,51,0,32,0,32,0,32 |
nvarchar2(2000) | 字4 | AL16UTF16 | Typ=1 Len=4: 91,87,0,52 |
汉1 -> AL32UTF8 (230,177,137,49,32)
230,177,137 -> 11100110 10110001 10001001 -> 11100110 10110001 10001001 -> 0110 1100 0100 1001 -> 0x 6C 49 -> 汉
49 -> character 1
32 -> blank character(blank-padded)字3 -> AL16UTF16(91,87,0,51,0,32,0,32,0,32)
91,87 -> 0x 5B 57 -> 字
0,51 -> character 3
0,32,0,32,0,32 -> 3 blank characters(blank-padded)
Character Datatypes Summary
Char | VarChar2 | NChar | NVarChar2 | |
---|---|---|---|---|
Definition | char(n [byte|char]) | varchar2(n [byte|char]) | nchar(n) | nvarchar2(n) |
Fixed-Variable | Fixed | Variable | Fixed | Variable |
Length Semantics | byte(default) char | byte(default) char | char | char |
Range in Bytes | 1~2000 | 1~4000 | 1~2000 | 1~4000 |
Character Encoding | AL32UTF8 | AL32UTF8 | AL16UTF16 | AL16UTF16 |
Maximum Latin Chars | 2000 | 4000 | 1000 | 2000 |
Maximum Chinese Chars(BMP) | 666 (2000/3) | 1333 (4000/3) | 1000 | 2000 |
Numeric Datatypes
Number Datatype
- Number[(p[,s])]
- p - Precision(total number of digits) (1~38)
- s - Scale(number of digits to the right of decimal point) (-84~127)
- 1~21 bytes (see dump in Internal Numeric Format section)
- Fixed-point
Number(p,s)
- Floating-point
Number
N | Number(p,s) | Stored As |
---|---|---|
123.45 | Number | 123.45 |
123.45 | Number(3) | 123 |
123.45 | Number(3,1) | exceeds precision |
123.45 | Number(3,-1) | 120 |
123.45 | Number(3,-2) | 100 |
123.45 | Number(3,-3) | 0 |
123.45 | Number(3,-4) | 0 |
123.45 | Number(5) | 123 |
123.45 | Number(5,1) | 123.5 |
123.45 | Number(5,2) | 123.45 |
123.45 | Number(5,3) | exceeds precision |
0.012 | Number(2,3) | 0.012 |
Internal Storage
SELECT '9.9999999999999999999999999999999999999e125',
dump(9.9999999999999999999999999999999999999E125),
'1e-130',
dump(1E-130),
'-1e-130',
dump(-1E-130),
'-9.9999999999999999999999999999999999999e125',
dump(-9.9999999999999999999999999999999999999E125),
0,
dump(0),
utl_raw.cast_to_number('FF65'),
dump(utl_raw.cast_to_number('FF65') ),
utl_raw.cast_to_number('00'),
dump(utl_raw.cast_to_number('00') )
FROM dual;
N | DUMP(N) | Description |
---|---|---|
9.99...9e125 (9 repeated 38 times) |
Typ=2 Len=20: 255,100,...,100 (100 repeated 19 times) |
Maximum Positive |
1e-130 | Typ=2 Len=2: 128,2 | Minimum Positive |
-1e-130 | Typ=2 Len=3: 127,100,102 | Maximum Negative |
-9.99...9e125 (9 repeated 38 times) |
Typ=2 Len=21: 0,2,...,2,102 (2 repeated 19 times) |
Minimum Negative |
0 | Typ=2 Len=1: 128 | Zero |
utl_raw.cast_to_number('FF65') | Typ=2 Len=2: 255,101 | Infinity |
utl_raw.cast_to_number('00') | Typ=2 Len=1: 0 | -Infinity |
-
Positive Number 12345.6789
Typ=2 Len=6: 195,2,24,46,68,90
- First byte 195 -> 1100 0011
Sign -> positive, the first bit is 1
Exponent -> 3, the following 7 bits (100 0011) - 64 (100 0000) = 3 - The other data (2,24,46,68,90) subtract 1
01, 23, 45, 67, 89 - Get the result
0.0123456789*100^3 = 12345.6789
- First byte 195 -> 1100 0011
-
Negative Number -12345.6789
Typ=2 Len=7: 60,100,78,56,34,12,102
First byte 60 -> 0011 1100
Sign -> negative, the first bit is 0
Exponent -> 3, the following 7 bits (011 1100) transfer to ones’ complement (100 0011) - 64 (100 0000) = 3-
100 subtract each of (100,78,56,34,12) then plus 1
The last byte is 102 for every negative number (exclude it)
01, 23, 45, 67, 89-
Why 102? -2 > -2.0001 and 62,99,102 > 62,99,101,100,102
Why 102?.png
-
Get the result
-0.0123456789*100^3 = -12345.6789
Zero, Infinite, -Infinite
Float Datatype
- Float[(p)]
- p - binary precision (1-126)
- binary precision * 0.30103 = decimal precision (digits = ceil(bits / log(2,10))
Float(n) | Float Value(1/3) | Number(n) | Number Value(1/3) |
---|---|---|---|
Float(1~3) | 0.3 | Number(1) | 0.3 |
Float(4~6) | 0.33 | Number(2) | 0.33 |
Float(126) | 0.3...3(3 repeated 38 times) | Number(38) | 0.3...3(3 repeated 38 times) |
Binary_Float Datatype
- Single-precision floating-point
- 5 bytes (4 data bytes + 1 length byte)
Internal Storage
IEEE754 Format wiki
- Sign (-1) ^ b31 = (-1) ^ 0= (+1)
- Exponent b30...b23 (0111 1100) = 124
- (1.b22...b0)2 = 1 + b22 ^(-1) + b21^(-2) + ... + b0^(-23) = 1 + 1^(-2) = 1.25
- Result = (+1) * 2 ^(124-127) * 1.25 = 0.15625
Oracle Format
select dump(0.15625f,16) from dual;
Typ=100 Len=4: be,20,0,0
Binary format 1011 1110 0010 0000 0000 0000 0000 0000
The first bit(sign bit) is different from IEEE754 format, all other bits are identical.
Binary_Double Datatype
- Double-precision floating-point
- 9 bytes (8 data bytes + 1 length byte)
Internal Storage
IEEE754 Format wiki
Numeric Datatypes Summary
Datatype | Precision | Value | Positive Range | Negative Range |
---|---|---|---|---|
Number | Decimal(0-9) | extract | 1.0E-130 ~ 1.0E126(not inclusive) | -1.0E126(not inclusive) ~ -1.0E-130 |
Float | Binary(0-1) | extract | 1.0E-130 ~ 1.0E126(not inclusive) | -1.0E126(not inclusive) ~ -1.0E-130 |
Binary_Float | Binary(0-1) | approximate | 1.17549E-38F ~ 3.40282E+38F | -3.40282E+38F ~ -1.17549E-38F |
Binary_Double | Binary(0-1) | approximate | 2.22507485850720E-308 ~ 1.79769313486231E+308 | -1.79769313486231E+308 ~ -2.22507485850720E-308 |
Date Datatypes
Alter date/timestamp/timestamp with tz format.
alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss';
alter session set nls_timestamp_format = 'yyyy-mm-dd hh24:mi:ssxff';
alter session set nls_timestamp_tz_format = 'yyyy-mm-dd hh24:mi:ssxff tzr';
Datetime Datatypes
Date
Timestamp
- Timestamp[(fractional_seconds_precision)]
- fractional_seconds_precision (0-9, default 6)
Timestamp with time zone
- TIMESTAMP [(fractional_seconds_precision)] WITH TIME ZONE
- fractional_seconds_precision (0-9, default 6)
Timestamp with local time zone
- TIMESTAMP [(fractional_seconds_precision)] WITH LOCAL TIME ZONE
- fractional_seconds_precision (0-9, default 6)
Internal Storage and Summary
DROP TABLE zz_date;
CREATE TABLE zz_date (
date_1 DATE,
timestamp_1 TIMESTAMP(9),
timestamp_2 TIMESTAMP(9) WITH TIME ZONE,
timestamp_3 TIMESTAMP(9) WITH LOCAL TIME ZONE
);
INSERT INTO zz_date (
date_1,
timestamp_1,
timestamp_2,
timestamp_3
) VALUES (
( '2019-03-04 17:30:40' ),
( '2019-03-04 17:30:40.000000256' ),
( '2019-03-04 17:30:40.000000512 +08:00' ),
( '2019-03-04 17:30:40.000001024' )
);
SELECT date_1,
dump(date_1),
timestamp_1,
dump(timestamp_1),
timestamp_2,
dump(timestamp_2),
timestamp_3,
dump(timestamp_3)
FROM zz_date;
Date | Timestamp | Timestamp TZ | Timestamp LTZ | |
---|---|---|---|---|
Value | 2019-03-04 17:30:40 | 2019-03-04 17:30:40.000000256 | 2019-03-04 17:30:40.000000512 +08:00 | 2019-03-04 17:30:40.000001024 |
Dump | Typ=12 Len=7: 120,119,3,4,18,31,41 | Typ=180 Len=11: 120,119,3,4,18,31,41,0,0,1,0 | Typ=181 Len=13: 120,119,3,4,10,31,41,0,0,2,0,28,60 | Typ=231 Len=11: 120,119,3,4,10,31,41,0,0,4,0 |
Length | 7 bytes | 11 bytes | 13 bytes | 11 bytes |
Century | 1st byte 120 20 = 120 - 100 |
<< | << | << |
Year in century | 2nd byte 119 19 = 119 - 100 |
<< | << | << |
Month | 3rd byte 3 |
<< | << | << |
Day | 4th byte 4 |
<< | << | << |
Hour | 5th byte 18 17 = 18 - 1 |
<< | << | << |
Minute | 6th byte 31 30 = 31 - 1 |
<< | << | << |
Second | 7th byte 41 40 = 41 - 1 |
<< | << | << |
Nanosecond | - | 8~11th bytes 0,0,1,0 256 = 0x 00 00 01 00 |
8~11th bytes 0,0,2,0 512 = 0x 00 00 02 00 |
8~11th bytes 0,0,4,0 1024 = 0x 00 00 04 00 |
Timezone hour | - | - | 12th byte 28 8 = 28 - 20 |
- |
Timezone minute | - | - | 13th byte 60 0 = 60 - 60 |
- |
Interval Datatypes
Interval year to month
- INTERVAL YEAR [(year_precision)] TO MONTH
- year_precision (0-9, default 2)
Interval day to second
- INTERVAL DAY [(day_precision)] TO SECOND [(fractional_seconds_precision)]
- day_precision (0-9, default 2)
- fractional_seconds_precision (0-9, default 6)
Internal Storage and Summary
DROP TABLE zz_interval;
CREATE TABLE zz_interval (
timestamp_1 TIMESTAMP(9),
interval_year_1 INTERVAL YEAR(9) TO MONTH,
interval_day_1 INTERVAL DAY(9) TO SECOND(9)
);
INSERT INTO zz_interval ( timestamp_1, interval_year_1, interval_day_1 ) VALUES (
( '2019-03-05 17:30:40.000000256' ),
INTERVAL '+100-2' YEAR ( 9 ) TO MONTH,
INTERVAL '10 1:2:3.000000001' DAY TO SECOND ( 9 )
);
INSERT INTO zz_interval ( timestamp_1, interval_year_1, interval_day_1 ) VALUES (
( '2019-03-05 17:30:40.000000256' ),
to_yminterval('100-2'),
to_dsinterval('10 1:2:3.000000001')
);
SELECT timestamp_1,
timestamp_1 + interval_year_1,
timestamp_1 + interval_day_1,
dump(interval_year_1),
dump(interval_day_1)
FROM zz_interval;
Interval year to month | Interval day to second | |
---|---|---|
Literal value | INTERVAL '+100-2' YEAR ( 9 ) TO MONTH | INTERVAL '10 1:2:3.000000001' DAY TO SECOND ( 9 ) |
To_interval value | to_yminterval('100-2') | to_dsinterval('10 1:2:3.000000001') |
Dump | Typ=182 Len=5: 128,0,0,100,62 | Typ=183 Len=11: 128,0,0,10,61,62,63,128,0,0,1 |
Length | 5 bytes | 11 bytes |
Description | A interval of 100 years and 2 months | A interval of 10d,1h,2m,3s and 1 nanosecond |
Year | 1~4th bytes 128,0,0,100 100 = 0x(80 00 00 64) - 0x(80 00 00 00) |
- |
Month | 5th byte 62 2 = 62 - 60 |
- |
Day | - | 1~4th bytes 128,0,0,10 10 = 0x(80 00 00 0A) - 0x(80 00 00 00) |
Hour | - | 5th byte 61 1 = 61 - 60 |
Minute | - | 6th byte 62 2 = 62 - 60 |
Second | - | 7th byte 63 3 = 63 - 60 |
Nanosecond | - | 8~11th bytes 128,0,0,1 1 = 0x(80 00 00 01) - 0x(80 00 00 00) |
LOB Datatypes
- Create file /tmp/abc.txt in database server file system
sh-4.2# echo 123456 > /tmp/abc.txt
- Create oracle directory object
CREATE DIRECTORY TMP_DIR AS '/tmp';
- Create lob table
CREATE TABLE zz_lob (
lob_id NUMBER,
clob_1 CLOB,
nclob_1 NCLOB,
blob_1 BLOB,
bfile_1 BFILE
);
CLOB
- Store large object data of characters encoded by NLS_CHARACTERSET
- Maximum size is (4 gigabytes - 1) * (database block size)
INSERT INTO zz_lob ( clob_1 ) VALUES (to_clob('123'));
NCLOB
- Store large object data of unicode character encoded by NLS_NCHAR_CHARACTERSET
- Maximum size is (4 gigabytes - 1) * (database block size)
INSERT INTO zz_lob ( nclob_1 ) VALUES (to_nclob('123'));
BLOB
- Store binary large object(image, video, audio..)
- Maximum size is (4 gigabytes - 1) * (database block size)
Store BLOB
DECLARE
src_lob BFILE := bfilename('TMP_DIR', 'abc.txt');
dest_lob BLOB;
BEGIN
INSERT INTO zz_lob ( lob_id, blob_1 ) VALUES ( 2, empty_blob() ) RETURNING blob_1 INTO dest_lob;
dbms_lob.open(src_lob, dbms_lob.lob_readonly);
dbms_lob.loadfromfile(
dest_lob => dest_lob,
src_lob => src_lob,
amount => dbms_lob.getlength(src_lob)
);
dbms_lob.close(src_lob);
COMMIT;
END;
BFILE
- Store a BFILE locator which points to a binary file in file system outside the database
- The BFILE locator (directory name and file name)
- Maximum size of BFILE is 4 gigabytes
Store BFILE
- bfilename
INSERT INTO zz_lob ( lob_id, bfile_1 ) VALUES (
1,
bfilename('TMP_DIR', 'abc.txt')
);
- Read BFILE by dbms_lob api
DECLARE
fil BFILE;
pos NUMBER := 1;
bat NUMBER := 5;
buf RAW(5);
BEGIN
SELECT bfile_1 INTO fil FROM zz_lob WHERE lob_id = 1;
-- fil:=BFILENAME('TMP_DIR','abc.txt');
dbms_lob.open(fil, dbms_lob.lob_readonly);
FOR i IN 1..ceil(dbms_lob.getlength(fil) / bat) LOOP
pos := 1 + bat * ( i - 1 );
dbms_output.put_line('i ' || i || ' start ' || pos || ' end ' || (pos + bat) );
dbms_lob.read(fil, bat, pos, buf);
dbms_output.put_line(utl_raw.cast_to_varchar2(buf) );
END LOOP;
dbms_lob.close(fil);
END;
- BFILE output
--i 1 start 1 end 6
12345
--i 2 start 6 end 11
6
Other Datatypes
Raw
Raw(n)
Store binary data/byte string
Variable length
-
MAX_STRING_SIZE
- STANDARD 2000 bytes
- EXTENDED 32767 bytes
DROP TABLE zz_raw;
CREATE TABLE zz_raw (
raw_1 RAW(5),
raw_2 RAW(5)
);
DELETE FROM zz_raw;
INSERT INTO zz_raw VALUES (
utl_raw.cast_to_raw('a'),
utl_raw.cast_from_number(1)
);
SELECT raw_1,
dump(raw_1, 16),
utl_raw.cast_to_varchar2(raw_1),
raw_2,
dump(raw_2, 16),
utl_raw.cast_to_number(raw_2)
FROM zz_raw;
Raw | Dump(Raw,16) | value |
---|---|---|
utl_raw.cast_to_raw('a') 0x61 |
Typ=23 Len=1: 61 | utl_raw.cast_to_varchar2 = a |
utl_raw.cast_from_number(1) 0xC102 |
Typ=23 Len=2: c1,2 | utl_raw.cast_to_number = 1 |
RowId URowId
RowId
Base64 string representing unique physical address of each row in heap-organized table.
- RowId Type
RowId type: 0 is restricted, 1 is extended
dbms_rowid.rowid_type(ROWID)
- Data Object Number
The unique indentifier of the object.
dbms_rowid.rowid_object(ROWID)
- File Number
The relative number of the datafile in the tablespace.
dbms_rowid.rowid_relative_fno(ROWID)
- Data Block Number
The relative block number in the datafile.
dbms_rowid.rowid_block_number(ROWID)
- Row Number
The relative rownum within the block.
dbms_rowid.rowid_row_number(ROWID)
URowId
Base 64 string representing the logical address of a row of an index-organized table.
- UROWID [(size)]
- size (4000bytes)
Reference
Oracle Datatypes
Fixed-point and floating-point representations of numbers
Introduction to Fixed Point Number Representation
How numbers are saved in oracle
Oracle dump number
Single-precision_floating-point
Double-precision_floating-point_format
ORAFAQ Data_types