SQL学习笔记

整体的SQL学习笔记,之后再分开来详细写。

查询 SELECT

Select查询某些属性列的语法
SELECT column, another_column, ... 
FROM mytable;
Select查询所有列
SELECT * 
FROM mytable;

条件查询

条件查询语法
SELECT column, another_column, ... 
FROM mytable
WHERE condition
    AND/OR another_condition
    AND/OR ...;
Operator Condition SQL Example
=,!=,<,<=,>,>= Standard numerical operators Col_name != 4
BETWEEN ... AND ... Number is within range of two values Col_name BETWEEN 1.5 AND 10.5
NOT BETWEEN ... AND ... Number is not within range of two values Col_name NOT BETWEEN 1 AND 10
IN(...) Number exists in a list Col_name IN (2,4,6)
NOT IN(...) Number does not exist in a list Col_name NOT IN(1,3,5)
字符串操作符
Operator Condition Example
= Case sensitive exact string comparison Col_name = "abc"
!= or <> Case sensitive exact string inequality comparison Col_name != "abcd"
LIKE Case insensitive exact string comparison Col_name LIKE "ABC"
NOT LIKE Case insensitive exact string inequality comparison Col_name NOT LIKE "ABCD"
% Used anywhere in a string to match a sequence of zero or more characters(only with LIKE or NOT LIKE) Col_name LIKE "%AT%"(matches "AT", "ATTIC","CAT" or even "BATS")
_ Used anywhere in a string to match a single character(only with LIKE or NOT LIKE) Col_name LIKE "AN_"(matches "AND", but not "AN")
IN(...) String exists in a list Col_name IN ("A", "B", "C")
NOT IN(...) String does not exist in a list Col_name NOT IN("D", "E", "F")

查询结果过滤Filtering和排序Sorting

选出唯一结果的语法
SELECT DISTINCT column, another_column, ...
FROM mytable
WHERE condition(s);
结果排序
SELECT column, another_column, ...
FROM mytable
WHERE condition(s)
ORDER BY column ASC/DESC;
通过LIMIT选取部分结果
SELECT column, another_column, ...
FROM mytable
WHERE condition(s)
ORDER BY column ASC/DESC
LIMIT num_limit OFFSET num_offset;

用JOINs进行多表联合查询

用INNER JOIN连接表的语法
SELECT column, another_table_column, ...
FROM mytable
INNER JOIN another_table
    ON mytable.id = another_table.id
WHERE condition(s)
ORDER BY column, ... ASC/DESC
LIMIT num_limit OFFSET num_offset;

INNER JOIN可以想成两个集合的交集。

Inner Join就是两个集合的交集

外连接OUTER JOINs

用LEFT/RIGHT/FULL JOIN做多表查询
SELECT column, another_column, ...
FROM mytable
INNER/LEFT/RIGHT/FULL JOIN another_table
    ON mytable.id = another_table.matching_id
WHERE condition(s)
ORDER BY column, ... ASC/DESC
LIMIT num_limit OFFSET num_offset;

LEFT JOIN

leftjoin

RIGHT JOIN

rightjoin

FULL JOIN

fulljoin

在查询中使用表达式

包含表达式的例子
SELECT particle_speed / 2 AS half_particle_speed
FROM physics_data
WHERE ABS(particle_position) * 10 > 500;

在查询中进行统计

对全部结果数据做统计
SELECT AGG_FUNC(column_or_expression) AS aggregate_description, ...
FROM mytable
WHERE constraint_expression;
常见统计函数
Function Description
COUNT(*), COUNT(column) 计数,统计非NULL的行数
MIN(column) 最小的一行
MAX(column) 最大的一行
AVG(column) 平均值
SUM(column) 求和
MySQL支持的统计函数
Name Description
AVG() Return the average value of the argument
BIT_AND() Return bitwise AND
BIT_OR() Return bitwise OR
BIT_XOR() Return bitwise XOR
COUNT() Return a count of the number of rows returned
COUNT(DISTINCT) Return the count of a number of different values
GROUP_CONCAT() Return a concatenated string
MAX() Return the maximum value
MIN() Return the minimum value
STD() Return the population standard deviation 标准差
STDDEV() Return the population standard deviation
STDDEV_POP() Return the population standard deviation
STDDEV_SAMP() Return the sample standard deviation
SUM() Return the sum
VAR_POP() Return the population standard variance 标准方差
VAR_SAMP() Return the sample variance 样本方差
VARIANCE() Return the population standard variance 标准方差
用分组的方式统计
SELECT AGG_FUNC(column_or_expression) AS aggregate_description, ...
FROM mytable
WHERE constraint_expression
GROUP BY column;
用HAVING进行筛选
SELECT group_by_column, AGG_FUNC(column_or_expression) AS aggregate_result_a
FROM mytable
WHERE condition
GROUP BY column
HAVING group_condition;

查询执行顺序

完整的SELECT查询
SELECT DISTINCT column, AGG_FUNC(column_or_expression), …
FROM mytable
    JOIN another_table
      ON mytable.column = another_table.column
    WHERE constraint_expression
    GROUP BY column
    HAVING constraint_expression
    ORDER BY column ASC/DESC
    LIMIT count OFFSET COUNT;
执行顺序:
  1. FROM 和 JOIN

    确定一个数据源表(含临时表)

  2. WHERE

    按要求进行数据筛选,并丢弃不符合要求的数据行,AS别名还不能在这个阶段使用

  3. GROUP BY

    数据进行分组,统计

  4. HAVING

    如用了GROUP BY分组,HAVING会在分组完成后对结果集再次筛选,AS别名不能使用

  5. SELECT

    对结果col简单筛选或计算,决定输出什么数据

  6. DISTINCT

    如果数据行有重复,DISTINCT将负责排重

  7. ORDER BY

    结果集确定的情况下,对结果进行排序,可以用AS别名

  8. LIMIT / OFFSET

    截取部分数据

处理日期的函数

SQL中处理日期的函数
#date(日期)返回日期时间的日期部分:
DATE(col_name)
#year(年)返回日期时间的年份:
YEAR(col_name)
#time(时间)返回日期时间的时间:
TIME(col_name)
#month(月份)返回日期时间的月份:
MONTH(col_name)
#day of week(星期)返回对应的是星期几,适用于MySQL:
DAYOFWEEK(col_name)
#day(日)返回日期时间的天数:
DAY(col_name)
#hour(小时)返回日期时间的小时:
HOUR(col_name)
#minute(分钟)返回日期时间的分钟:
MINUTE(col_name)
#second(秒)返回日期时间的秒钟:
SECOND(col_name)
增减日期
#adddate(增加日期)增加或减少一个日期(年季月日时),这里有三种写法:
ADDDATE(date, INTERVAL value addunit);
DATE_ADD(date, INTERVAL value addunit);
ADDDATE(date, days)

常见的addunit可取值有:

  • Year
  • Quarter
  • Month
  • Day
  • Week
  • Hour
  • Minute
  • Second
  • Millisecond
增减时间
ADDTIME(datetime, addtime)
当前时间
#curdate(当前日期)返回当前日期:
CURDATE()
#curtime(当前时间)返回当前时间:
CURTIME()
#now(现在)返回当前日期时间:
NOW()
其他日期相关函数
#datediff(日期区别)计算两个日期的差值:
DATEDIFF(date1, date2)
#dayofweek(星期中的哪一天)返回日期为星期几:
DAYOFWEEK(date)
#date_format(格式)返回一个格式化的日期时间:
DATE_FORMAT(date, format)

format(格式)可以取下表的值:

  • %a:工作日缩写名称(星期日至星期六)
  • %b:月份的缩写(1月至12月)
  • %c:数字月份名称(0到12)
  • %D:一个月的天,以数字值后跟后缀(第一,第二,第三,...)
  • %d:月份中的天,以数值(01到31)
  • %e:每月的天,以数值(0到31)
  • %f:微秒(000000至999999)
  • %H:小时(00到23)
  • %h:小时(00到12)
  • %I:小时(00到12)
  • %i:分钟(00至59)
  • %j:一年中的某天(001至366
  • %k:小时(0到23)
  • %l:小时(1到12)
  • %M:月的全称(1月至12月)
  • %m:月名称(作为数字值(00到12))
  • %p:AM或PM
  • %r:以12小时AM或PM格式显示的时间(hh:mm:ss AM / PM)
  • %S:秒(00至59)
  • %s:秒(00至59)
  • %T:时间,以24小时格式(hh:mm:ss)
  • %U:周,其中星期日是一周的第一天(00到53)
  • %u :Week,其中星期一是一周的第一天(00到53)
  • %V:周,其中星期日是一周的第一天(01到53)。与%X一起使用
  • %v:周,其中星期一是一周的第一天(01到53)。与%x一起使用
  • %W:工作日名称的完整名称(星期日至星期六)
  • %w:星期几,星期天= 0,星期六= 6
  • %X:星期的年份,其中星期日是一周的第一天。与%V一起使用
  • %x:一周的第一年中的一周的年份。与%v一起使用
  • %Y:年,为4位数字
  • %y:年,为2位数字数值
常用对日期的筛选
#几个小时内的数据
DATE_SUB(NOW(), INTERVAL 5 HOUR)
#今天
select * from 表名 where to_days(时间字段名) = to_days(now());
#昨天
SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ) - TO_DAYS( 时间字段名) <= 1
#7天
SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(时间字段名)
#近30天
SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(时间字段名)
#本月
SELECT * FROM 表名 WHERE DATE_FORMAT( 时间字段名, '%Y%m' ) = DATE_FORMAT( CURDATE( ) , '%Y%m' )
#上一月
SELECT * FROM 表名 WHERE PERIOD_DIFF( date_format( now( ) , '%Y%m' ) , date_format( 时间字段名, '%Y%m' ) ) =1
#查询本季度的数据
SELECT * FROM order WHERE QUARTER(时间字段名)=QUARTER(NOW())
#查询上季度的数据
SELECT * FROM order WHERE QUARTER(时间字段名)=QUARTER(DATE_SUB(NOW(),INTERVAL 1 QUARTER))
#查询当年(今年)的数据
SELECT * FROM `order` WHERE YEAR(order_time)=YEAR(NOW())
#查询去年的数据
SELECT * FROM `order` WHERE YEAR(order_time)=YEAR(DATE_SUB(NOW(),INTERVAL 1 YEAR))

文本处理函数

大小写转换
#upper(大写)将string(串)转换为大写:
UPPER('string')
#lower(小写)将string(串)转换为小写:
LOWER('string')
字符串拼接
CONCAT(col_name, col_name)
#加入别的字符需要使用引号
文本数据的选择
#Left(左)返回串左边选定多少的字符串:
LEFT(string, number)
#Right(右)返回串右边选定多少的字符串:
RIGHT(string, number)
#Length(长度)返回串的字节长度:
LENGTH(string)
#Char_length返回串的汉字字符长度:
CHAR_LENGTH(string)
定位
LOCATE(substring, string, start)
#其中,substring为只想要检索的子串,string是原文本,start是位置(数字),留意空格也是算一个位置的。
修剪
#Ltrim(左,修剪)去掉串左边的空格:
LTRIM('string')
#Rtrim(右,修剪)去掉串右边的空格:
RTRIM('string')
#Substring(子,串)返回子串的字符:
SUBSTRING(string, start, length)

数值处理函数

常用数值处理函数
#abs(absolute value, 绝对值)可以返回一个数的绝对值:
ABS(col_name)

#mod(余数), 返回除之后的余数,这里有三种写法:
MOD(x,y)
x MOD y
x % y
#其中,x为被除数,y为除数

#rand(random, 随机),返回一个随机数:
RAND()

#或者可以设定一个可以重现的”种子(seed)“:
RAND(seed)

#sqrt(平方根)返回一个数的平方根:
SQRT(col_name)
#这里数值必须大于0
聚集函数
#avg(average, 平均数),计算特定列值的平均数。
AVG(col_name)

#count(计数), 确定表中行的数目或符合特定条件的行的数目。
COUNT(*)
#对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。
COUNT(column)
#对特定列中具有值的行进行计数,忽略 NULL值。

#max(最大)返回指定列中的最大值。
MAX(column)
#min(最小)返回指定列中的最小值。
MIN(column)

#sum(总计)用来返回指定列值的和
SUM(column)

组合与联结

UNION

可以将多条SELECT语句的结果组合成单个结果集。

适用UNION的两种基本情况:

  • 在单个查询中从不同的表返回类似结构的数据;
  • 对单个表执行多个查询,按单个查询返回数据
SELECT A.姓名, B.薪资
FROM 职员 AS A
LEFT JOIN 薪水 AS B
USING (职位编号)
UNION
SELECT A.姓名, B.薪资
FROM 职员 AS A
RIGHT JOIN 薪水 AS B
USING (职位编号)

UNION将去除重复数据行;UNION ALL 为全集合,包括重复行。

文本检索和编辑

LIKE & REGEXP

LIKE匹配整个列,而REGEXP匹配的是列值。

如果被匹配的文本在列值中出现:

  • LIKE将不会找到它,相应的行也不被返回(除非使用通配符)。
  • REGEXP将会找到它,相应的行将被返回
WHERE col_name REGEXP 'value'

MySQL中的正则表达式匹配(自版本 3.23.4后)不区分大小写,即大写和小写被视作一样。为区分大小写,可使用BINARY关键字。

同时对多个串进行匹配

可以用OR(或者),即为符号“|”

WHERE col_name REGEXP 'value_1|value_2|value_3'

可以适用方括号([])来简化匹配

WHERE col_name REGEXP '[value1value2value3]value'

例:

SELECT prod_name
FROM products
WHERE prod_name REGEXP '1000|2000|3000'
ORDER BY prod_name
# 可以写为:
SELECT prod_name AS 利用方括号偷懒
FROM products
WHERE prod_name REGEXP '[123]000'
ORDER BY prod_name
否定匹配

“^”在字符集合中表示否定。

[123]匹配数字1、2和3,但是[^123]匹配所有除了1、2和3的任何东西。

集合匹配

可以使用集合或字符类来匹配。

说明
[:alnum:] 任意字母和数字,同[a-zA-z0-9]
[:alpha:] 任意字符,同[a-zA-Z]
[:blank:] 空格和制表符,同[\\t]
[:cntrl:] ASCII控制字符
[:digit:] 任意数字,同[0-9]
[:lower:] 任意小写字母,同[a-z]
[:print:] 任意可打印字符
[:punct:] 既不在[:alnum:]又不在[:cntrl:]中的任意字符
[:space:] 包括空格在内的任意空白字符,同[\\f\\n\\r\\t\\v]
[:upper:] 任意大写字母,同[A-Z]
[:xdigit:] 任意十六进制数字,同[a-fA-F0-9]
转义字符与元字符

双反斜杠“\“来对特殊字符进行转义(escaping)。

空白元字符

元字符 说明
\\f 换页
\\n 换行
\\r 回车
\\t 制表
\\v 纵向制表

重复元字符

元字符 说明
* 0个或多个匹配
+ 1个或多个匹配
? 0个或1个匹配
{n} 指定数目的匹配
{n,} 不少于指定数目的匹配
{n,m} 匹配数目的范围

定位符

元字符 说明
^ 文本的开始
$ 文本的结尾
[[:<:]] 词的开始
[[:>:]] 词的结尾

全文本搜索

聚集索引与非聚集索引

正文内容本身就是一种按照一定规则排列的目录便是聚集索引

目录纯粹是目录,正文纯粹是正文的排序方式便是非聚集索引

开启索引

启用全文本搜索的方式非常简单,通过FULLTEXT(全文本)子句便可在create table中直接对列进行索引:

CREATE TABLE 表名(列1 INT, 列2 CHAR(100), 列3 TEXT, FULLTEXT(列3))
扩展查询

在使用查询扩展时,MySQL对数据和索引进行两遍扫描来完成搜索:

  • 进行一个基本的全文本搜索,找出与搜索条件匹配的所有行;
  • MySQL检查这些匹配行并选择所有有用的词;
  • MySQL再次进行全文本搜索,这次不仅使用原来的条件,并且还使用所有有用的词。
WHERE MATCH(列名) AGAINST('想要搜索的文本' WITH QUERY EXPANSION)
布尔模式

利用布尔模式,我们不必定义FULL TEXT索引即可使用全文本搜索,并且可以直接根据且不限于如下的细节来锁定内容:

  • 要匹配的词;
  • 要排斥的词(如果某行包含这个词,则不返回该行,即使它包含其他指定的词);
  • 排列提示(指定某些词比其他词更重要,更重要的词等级更高);
  • 表达式分组。
WHERE MATCH(列名) AGAINST('想要搜索的文本' IN BOOLEAN MODE)
布尔操作符 说明
+ 包含,词必须存在
- 排除,词必须不出现
> 包含,而且增加等级值
< 包含,且减少等级值
() 把词组成子表达式
~ 取消一个词的排序值
* 词尾的通配符
"" 定义一个短语

插入数据INSERT

INSERT(插入)是用来插入/添加行到数据库表的。利用INSERT我们可以插入如下数:

  • 完整的行;
  • 行的一部分;
  • 多个不同的行;
  • 查询/计算的结果。
普通INSERT
INSERT INTO 职员 
VALUE (1, '张三', 1638264, 2);

更为安全的做法是在INSERT INTO中定义信息的次序:

INSERT INTO 职员(编号, 姓名, 电话, 职位编号)
VALUE (1, '张三', 1638264, 2);

INSERT的降级,low priority:

#原本的INSERT语句:
INSERT INTO TABLE 表 VALUE(值1, 值2,值3, ...)
#降级INSERT的运行顺序:
INSERT LOW_PRIORITY INTO TABLE 表 VALUE(值1, 值2,值3, ...)

更新UPDATE与删除DELETE

UPDATE

基本的UPDATE语句由三部分构成:

  • 待更新的表;
  • 待更新的列名和新的值;
  • 更新的过滤条件。
UPDATE 表名
SET 列名1 = '新的值1', #注意若是更新多个列的时候,这里需要要用逗号隔开。
列名2 = '新的值2'
WHERE 条件
DELETE
DELETE FROM 表名
WHERE 条件

表的操作

删除表
DROP TABLE 表名;
重命名表
RENAME TABLE 表一 TO 表名;
NULL值限定

在建立表的过程中,其实我们可以强制性规定指定列是否可以允许出现NULL值:

CREATE TABLE 例子
(列名一 字符属性 NOT NULL,
列名二 字符属性 NULL);
主外键

主键值必须唯一,表中的每个行必须具有唯一的主键值。

如果主键使用单个列,则它的值必须唯一。如果使用多个列,则这些列的组合值必须唯一

PRIMARY KEY(列名一, 列名二, ...)

外键:

FOREIGN KEY (列名一) REFERENCES 表名二(列名二)
自动增量

AUTO_INCREMENT告诉MySQL,本列每当增加一行时自动增量。

列名 字符属性 NOT NULL AUTO_INCREMENT

想要找到最后一个AUTO_INCREMENT的值,可以使用如下代码:

SELECT LAST_insert_ID()
指定默认

如果在插入行时没有给出值,MySQL允许指定此时使用的默认值。DEFAULT关键字指定:

列名 字符属性 NOT NULL DEFAULT 数值
更新表定义

为更新表定义,可使用ALTER TABLE语句。

例子:

CREATE TABLE 订单
(订单号 int NOT NULL AUTO_INCREMENT, 
顾客ID int NOT NULL, 
PRIMARY KEY(订单号));
INSERT INTO 订单(顾客ID)
VALUES(1),(8),(13),(6),(24),(54);
ALTER TABLE 订单
ADD 商品数量 INT NOT NULL DEFAULT 1

视图

视图的作用

包含了SQL查询的视图可以:

  • 反复重用SQL语句;

  • 简化复杂的SQL操作;

  • 使用表的组成部分而不是整个表;

  • 保护数据:

    • 可以给用户授予表的特定部分的访问权限而不是整个表的访问权限;
  • 更改数据格式和表示:

    • 视图可返回与底层表的表示和格式不同的数据。
视图的常见规则
  • 视图的命名必须唯一,不得与别的视图或是表相同;
  • 创建视图的数量没有限制,但必须有相对应的访问权限;
  • 视图可以互相嵌套;
  • ORDER BY可以用在视图中,但若是使用视图时也使用了ORDER BY,那视图中的ORDER BY将会被覆盖;
  • 视图不可索引;
  • 视图可以与表同时使用。
视图创建

创建视图:

CREATE VIEW 视图名称

查看创建视图:

SHOW CREATE VIEW 视图名称

删除视频:

DROP VIEW 视图名称

更新/覆盖视图:

CREATE OR REPLACE VIEW 视图名称

存储过程

把流程分门别类地建立起一个模版,不但会大幅便捷我们的操作,统一我们的代码以保证数据的一致性,还可以简化对变动的管理。这就是存储过程

存储过程的执行
CALL 过程名称(参数);
创建存储过程
DELIMITER // #使用“//”作为新的语句结束分隔符
CREATE PROCEDURE 过程名称(参数)
BEGIN #(开始)
  储存内容条件语句;
END// #(结束)
DELIMITER ; #恢复为原来的语句分隔符“;”
删除存储过程
DROP PROCEDURE 过程名称;
#注意,此处不需要参数的括号。
参数

MySQL支持三种类型的参数:

  • IN(传递给存储过程);
  • OUT(从存储过程传出);
  • INOUT(对存储过程传入和传出)。

游标CURSOR

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