Oracle Datatypes

Character Datatypes

NLS parameters (V$NLS_PARAMETERS)

  • NLS_LENGTH_SEMANTICS
    1. BYTE (default)
    2. CHAR
  • NLS_CHARACTERSET
    Character encoding of CHAR, VARCHAR2 and CLOB datatypes
    eg: AL32UTF8 (UTF8 not recommended)
    1. Latin characters -> 1 byte
    2. Chinese characters(in BMP) -> 3 bytes
  • NLS_NCHAR_CHARACTERSET
    Character encoding of NCHAR, NVARCHAR2 and NCLOB datatypes
    eg: AL16UTF16 (UTF8 not recommended)
    1. Latin characters -> 2 bytes
    2. 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

    1. 0 < n <= 666
      We can store n(bytes = 3*n <= 1998) Chinese chars.
    2. 666 < n <= 2000
      You can't store n(bytes = 3*n > 2000) Chinese chars.

VarChar2

  • Store character data encoded by NLS_CHARACTERSET

  • MAX_STRING_SIZE

    1. STANDARD 4000 bytes
    2. 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

    1. 0 < n <= 1333
      We can store n(bytes = 3*n <= 3999) Chinese chars.
    2. 1333 < n <= 4000
      You can't store n(bytes = 3*n > 2000) Chinese chars.

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
    1. STANDARD 4000 bytes
    2. 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

    1. First byte 195 -> 1100 0011
      Sign -> positive, the first bit is 1
      Exponent -> 3, the following 7 bits (100 0011) - 64 (100 0000) = 3
    2. The other data (2,24,46,68,90) subtract 1
      01, 23, 45, 67, 89
    3. Get the result
      0.0123456789*100^3 = 12345.6789
  • Negative Number -12345.6789
    Typ=2 Len=7: 60,100,78,56,34,12,102

    1. 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

    2. 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
    3. 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

wiki 4 bytes float - bits

wiki 4 byte float - result formula
  1. Sign (-1) ^ b31 = (-1) ^ 0= (+1)
  2. Exponent b30...b23 (0111 1100) = 124
  3. (1.b22...b0)2 = 1 + b22 ^(-1) + b21^(-2) + ... + b0^(-23) = 1 + 1^(-2) = 1.25
  4. 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

wiki 8 bytes double - bits

wiki 8 bytes double - result formula

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

    1. STANDARD 2000 bytes
    2. 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容