SQL基础

查询当前会话产生的所有profiles;
mysql>select @@profileing;
mysql>set profiling=1;
mysql>show profiles;
//查询指定的query id
mysql>show profiles for query 2;
DDL的基础语法
  1. 对数据库进行定义
CREATE DATABASE nba; // 创建一个名为nba的数据库
DROP DATABASE nba; // 删除一个名为nba的数据库

2.对数据表进行定义

CREATE TABLE [](字段名 数据类型,......)
  1. 改变表结构
//添加字段
ALTER TABLE player ADD (age int(11));
//修改字段名
ALTER TABLE player RENAME COLUMN age to player_age
//修改字段的数据类型
ALTER TABLE player MODIFY (player_age float(3,1));
//删除字段
ALTER TABLE player DROP COLUMN player_age;
数据表常见约束
  • 主键约束:UNIQUE+NOT NULL
  • 外键约束
  • 唯一性约束
  • NOT NULL :不应该为空,必须有值
  • DEFAULT:默认值
  • CHECK约束:检查特定字段取值范围的有效性,CHECK约束的结果不为0
去除重复行:DISTINCT
  • DISTINCT 需要放在所有列名的前面
  • DISTINCT 其实是对后面所有列名的组合进行去重
如何排序检索数据:ORDER BY
  • 排列的列名:ORDER BY后面可以有一个或多个列名,如果是多个列名,会按照第一个列先进行排序,当第一列的值相同的时候,再按照第二列进行排序。
  • 排序的顺序:ORDER BY后面可以注明排序规则,ASC代表递增排序,DESC代表递减顺序。默认按照ASC递增排序。
  • 非选择列排序:ORDER BY可以使用非选择列进行排序,所以即使在SELECT后面没有这个列名,同样可以放到ORDER BY后面进行排序。
约束返回结果的数量

不同的DBMS中使用的关键字不同:

// MySQL ,PostgreSQL,MariaDB和SQLite中使用LIMIT关键字,并且必须放到select语句的最后面
SELECT name, hp_max FROM heros ORDER BY hp_max DESC LIMIT 5;
// SQL Sever和Access,需要使用TOP关键字
SELECT TOP 5 name, hp_max FROM heros ORDER BY hp_max DESC;
// DB2,使用FETCH FIRST 5 ROWS ONLY这样的关键字
SELECT name, hp_max FROM heros ORDER BY hp_max DESC FETCH FIRST 5 ROWS ONLY
// Oracle,需要基于ROWNUM来统计行数
SELECT name, hp_max FROM heros WHERE ROWNUM <=5 ORDER BY hp_max DESC
SELECT的执行顺序
  • 关键字的顺序不能颠倒
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
  • SELECT语句的执行顺序
FROM > WHERE > GROUP BY > HAVING > SELECT的字段 > DISTINCT > ORDER BY > LIMIT
SQL数据过滤:WHERE子句

WHERE子句的基本格式:

SELECT ……(列名) FROM ……(表名) WHERE ……(子句条件)
  • 比较运算符
    image.png

    注意:使用BETWEEN...AND...的时候,是可以取到最大值和最小值的
  • 逻辑运算符
    image.png

    注意:当WHERE子句中同时出现(),AND和OR操作符的时候,优先级顺序:()> AND > OR
  • 通配符
    使用关键字:LIKE
    1. 匹配0个或多个字符:%
    2. 匹配一个字符:_
SELECT name FROM heros WHERE name LIKE '_%太%'

注意:尽量少用通配符,因为它需要消耗数据库更长的时间来进行匹配,索引可能失效

SQL函数
  1. 算数函数


    image.png
  2. 字符串函数


    image.png
  3. 日期函数


    image.png
  4. 转换函数
    image.png

    CAST 函数在转换数据类型的时候,不会四舍五入,如果原数值有小数,那么转换为整数类型的时候就会报错。不过你可以指定转化的小数类型,在 MySQL 和 SQL Server 中,你可以用DECIMAL(a,b)来指定,其中 a 代表整数部分和小数部分加起来最大的位数,b 代表小数位数,比如DECIMAL(8,2)代表的是精度为 8 位(整数加小数位数最多为 8 位),小数位数为 2 位的数据类型。所以SELECT CAST(123.123 AS DECIMAL(8,2))的转换结果为 123.12
    注意: 大部分 DBMS 会有自己特定的函数,这就意味着采用 SQL 函数的代码可移植性是很差的,因此在使用函数的时候需要特别注意。
SQL聚集函数,分组过滤
  1. 聚集函数如下:
    image.png

    注意:
  • COUNT()会忽略值为 NULL 的数据行,而 COUNT(*) 只是统计数据行数,不管某个字段是否为 NULL
  • AVG、MAX、MIN 等聚集函数会自动忽略值为 NULL 的数据行
  1. 对数据进行分组:GROUP BY子句
  2. 对分组数据进行过滤:HAVING
    HAVING 的作用和 WHERE 一样,都是起到过滤的作用,只不过 WHERE 是用于数据行,而 HAVING 则作用于分组。如果把 HAVING 替换成了 WHERE,SQL 则会报错。HAVING 支持所有 WHERE 的操作,因此所有需要 WHERE 子句实现的功能,你都可以使用 HAVING 对分组进行筛选。
  3. 使用顺序不可颠倒
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
子查询
  1. 什么是关联子查询和非关联子查询:
  • 非关联子查询:子查询从数据表中查询了数据结果,如果这个数据结果只执行了一次,然后这个数据结果作为主查询的条件进行执行,那么这样的查询叫做关联子查询;
    SELECT player_name, height FROM player WHERE height = (SELECT max(height) FROM player);
    
  • 关联子查询:如果子查询需要执行多次,即采用循环的方式,先从外部查询开始,每次都传入子查询进行查询,然后再将结果反馈给外部,这种嵌套的执行方式就称为关联子查询
    SELECT player_name, height FROM player WHERE height = (SELECT max(height) FROM player)
    
  1. EXISTS子查询
    关联子查询通常会和EXISTS一起来使用,EXISTS子查询用来判断条件是否满足,满足的话为True,不满足为False。
    SELECT player_id, team_id, player_name FROM player WHERE EXISTS (SELECT player_id FROM player_score WHERE player.player_id = player_score.player_id)
    
  2. 集合比较子查询
    集合比较子查询的作用是与另一个查询结果集进行比较,可以在子查询中使用IN,ANY,ALL和SOME操作符


    image.png
     //IN
     SELECT player_id, team_id, player_name FROM player WHERE player_id in (SELECT player_id FROM player_score WHERE player.player_id = player_score.player_id)
     //ANY
     SELECT player_id, player_name, height FROM player WHERE height > ANY (SELECT height FROM player WHERE team_id = 1002)
     //ALL
     SELECT player_id, player_name, height FROM player WHERE height > ALL (SELECT height FROM player WHERE team_id = 1002)
    
  3. 子查询作为计算字段
 SELECT team_name, (SELECT count(*) FROM player WHERE player.team_id = team.team_id) AS player_num FROM team
连接
  1. 内连接:将多个表之间满足连接条件的数据行查询出来。包括等值连接,非等值连接和自连接
// 自然连接
SELECT player_id, a.team_id, player_name, height, team_name FROM player as a, team as b WHERE a.team_id = b.team_id
// ON连接
SELECT player_id, player.team_id, player_name, height, team_name FROM player JOIN team ON player.team_id = team.team_id
// USING连接
SELECT player_id, team_id, player_name, height, team_name FROM player JOIN team USING(team_id)
// 自连接
SELECT b.player_name, b.height FROM player as a JOIN player as b ON a.player_name = '布雷克-格里芬' and a.height < b.height
  1. 外连接:会返回一个表中的所有记录,以及另外一个表中匹配的行。包括左外连接,右外连接和全连接
// 左外连接
SELECT * FROM player LEFT JOIN team ON player.team_id = team.team_id
// 右外连接
SELECT * FROM player LEFT JOIN team ON player.team_id = team.team_id
// 全连接
SELECT * FROM player FULL JOIN team ON player.team_id = team.team_id
  1. 交叉连接:也称为笛卡尔积,返回左表中每一行与右表中每一行的组合
SELECT * FROM player CROSS JOIN team
视图 VIEW

视图作为一张虚拟表,帮我们封装来底层与数据表的接口。它相当于是一张表或多张表的数据结果集。

  1. 创建视图:CREATE VIEW
CREATE VIEW view_name AS
SELECT column1, column2
FROM table
WHERE condition

实际上就是我们在 SQL 查询语句的基础上封装了视图 VIEW,这样就会基于 SQL 语句的结果集形成一张虚拟表。其中 view_name 为视图名称,column1、column2 代表列名,condition 代表查询过滤条件。
当视图创建之后,就相当于一个虚拟表,可以直接使用:

SELECT * FROM player_above_avg_height
  1. 嵌套视图
    当创建一张视图后,可以在其基础上继续创建视图
CREATE VIEW player_above_above_avg_height AS
SELECT player_id, height
FROM player
WHERE height > (SELECT AVG(height) from player_above_avg_height)
  1. 修改视图:ALTER VIEW
ALTER VIEW view_name AS
SELECT column1, column2
FROM table
WHERE condition
  1. 删除视图:DROP VIEW
DROP VIEW view_name
存储过程 PROCEDURE

存储过程是由SQL语句和流控制语句构成的语句集合,和函数一样可以接收输入参数,也可以返回输出参数给调用者,返回计算结果。一旦存储过程被创建出来,直接通过调用存储过程名即可。

  1. 定义一个存储过程:
// 创建
CREATE PROCEDURE 存储过程名称([参数列表])
BEGIN
  需要执行的语句
END    
// 调用存储过程
call 存储过程名称;
  • CREATE PROCEDURE:创建存储过程
  • DROP PROCEDURE:删除存储过程
  • ALTER PROCEDURE:更新存储过程
  1. 参数类型


    image.png
  2. DELIMITER:

DELIMITER //
CREATE PROCEDURE `add_num`(IN n INT)
BEGIN
     DECLARE i INT;
     DECLARE sum INT;
     
     SET i = 1;
     SET sum = 0;
     WHILE i <= n DO
            SET sum = sum + i;
            SET i = i +1;
     END WHILE;
     SELECT sum;
END //
DELIMITER ;

DELIMITER:用来临时定义新的结束符。默认情况下SQL采用(;)作为结束符,这样当存储过程每一句SQL结束后,采用分号作为结束符就相当于告诉SQL可以执行这一句来。存储过程作为一个整体,不希望SQL逐行执行,而是采用存储过程整段执行,因此就需要临时定义新的DELIMITER,新的结束符可以用(//)或者($$)。存储过程完成后需要重新把结束符换回(;)。

  1. 控制流语句
  • BEGIN...END:中间包含多个语句,每个语句都以(;)结束符;
  • DECLEAR:用来声明变量,使用的位置在BEGIN...END语句中间,而且需要在其他语句使用之前进行变量的声明;
  • SET:赋值语句,用于对变量进行赋值;
  • SELECT...INTO:把从数据表中查询的结果存放到变量中,也就是为变量赋值;
  • IF...THEN...ENDIF:条件判断语句,还可以在IF...THEN...ENDIF中使用ELSE和ELSEIF来进行条件判断;
  • CASE:用于多条件的分支判断;
  • LOOP,LEAVE,ITERATE:LOOP是循环语句,使用LEAVE可以跳出循环,使用ITERATE可以进入下一次循环;
  • REPEATE...UNTIL...END REPEAT:首先执行一次循环,然后在UNTIL中进行表达式判断,满足就退出,即END REPEAT,不满足继续执行循环;
  • WHILE...DO...END WHILE:先进行条件判断,满足条件进行循环,不满足退出循环
事务 transaction

SHOW ENGINS查看当前存储引擎是否支持事务


image.png

InnoDB支持事务,而MyISAM不支持

  1. 事务的特性:ACID
  • A,原子性(Atomicity),就是不可分割
  • C,一致性(Consistency),指的是数据库在进行事务操作后,会由原来的一致状态,变成另一种一致的状态。也就是说事务提交后,或者事务发送回滚后,数据库的完整性约束不能被破坏
  • I,隔离性(Isolation),每个事务彼此独立,不会受到其他是否的执行影响
  • D,持久性(Durablity),事务提交后对数据的修改是持久的。即使在系统出故障的情况下,数据的修改依然有效。当事务完成,数据库的日志会更新,这时通过日志,让系统恢复到最后一次成功的更新状态
  1. 事务的常用控制语句
  • START TRANSACTION或者BEGIN,显示开启一个事务;
  • COMMIT:提交事务;
    Oracle默认不自动提交,需要手写COMMIT,MySQL默认自动提交,也可以进行配置:
    mysql> set autocommit =0;  //关闭自动提交
    mysql> set autocommit =1; //开启自动提交
    
  • ROLLBACK或者ROLLBACK TO [SAVEPOINT] ,回滚事务。可以撤销正在进行的所有没有提交的修改,或者将事务回滚到某个保存点;
  • SAVEPOINT:在事务中创建保存点,方便后续针对保存点进行回滚,一个事务中可以设置多个保存点;
  • RELEASE SAVEPOINT:删除某个保存点;
  • SET TRANSACTION:设置事务的隔离级别;
  1. 事务并发处理异常
    • 脏读(Dirty Read):读到了其他事务还没有提交的数据;
    • 不可重复读(Unrepeatable Read):对某数据进行读取,发现两次读取的结果不同,也就是说没有读到相同的内容。这时因为有其他事务对这个数据同时进行了修改或删除;
    • 幻读(Phantom Read):事务A根据条件查询得到了N条数据,但此时事务B更改或者增加了M条符合事务A查询条件的数据,这样当事务A再次进行查询的时候发现会有N+M条数据,产生了幻读

四种隔离级别:


image.png

- 读未提交:也就是允许读到未提交的数据,这种情况下查询是不会使用锁的,可能会产生脏读,不可重复读,幻读等情况
- 读已提交:只能读到已提交的内容,可以避免脏读的产生,但是如果要避免不可重复读或者幻读,需要在SQL查询的时候编写带加锁的SQL语句
- 可重复读:保证一个事务在相同查询条件下两次查询得到的数据结果一致,避免不可重复读和脏读,但是无法避免幻读
- 可串行化:将事务进行串行化,也就是在一个队列中按照顺序执行,是最高级别的隔离登记,但是牺牲了系统的并发性

游标
在数据库中,游标是一种临时的数据库对象,可以指向存储在数据库表中的数据行指针。这里游标充当了指针的作用,可以通过操作游标来对数据进行操作。

使用游标的步骤:

  1. 定义游标:
DECLEAR cursor_name CURSOR FOR select_statement;  //select_statement代表SELECT语句
  1. 打开游标:
OPEN cursor_name;

打开游标的时候SELECT语句的查询结果集就会送到游标工作区

  1. 从游标中取得数据:
FETCH cursor_name INTO var_name,...;

使用cursor_name这个游标来读取当前行,并且将数据保存到var_name这个变量中,游标指针指到下一行。如果游标读取的数据行有多个列名,则在INTO关键字后面赋值给多个变量即可。

  1. 关闭游标:
CLOSE cursor_name;
  1. 释放游标:
DEALLOCATE cursor_name ;
  游标实际上是面向过程的思维方式,与面向集合的思维方式不同的地方在于,游标更加关注“如何执行”。我们可以通过游标更加精细、灵活地查询和管理想要的数据行。有的时候,我们需要找特定数据,用 SQL 查询写起来会比较困难,比如两表或多表之间的嵌套循环查找,如果用 JOIN 会非常消耗资源,效率也可能不高,而用游标则会比较高效。
虽然在处理某些复杂的数据情况下,使用游标可以更灵活,但同时也会带来一些性能问题,比如在使用游标的过程中,会对数据行进行加锁,这样在业务并发量大的时候,不仅会影响业务之间的效率,还会消耗系统资源,造成内存不足,这是因为游标是在内存中进行的处理。如果有游标的替代方案,我们可以采用替代方案。
范式
  • 1NF 需要保证表中每个属性都保持原子性;
  • 2NF 需要保证表中的非主属性与候选键完全依赖;
  • 3NF 需要保证表中的非主属性与候选键不存在传递依赖;
索引

索引就是帮助数据库管理系统高校获取数据的数据结构。

  1. 索引分类
  • 功能逻辑划分:普通索引,唯一索引,主键索引
    普通索引:基础索引,没有任何约束,主要用于提高查询效率;
    唯一索引:在普通索引基础上增加了数据唯一的约束,一张数据表里面可以有多个唯一索引;
    主键索引:在唯一索引的基础上增加了不为空的约束,也就是NOT NULL+UNIQUE,一张表里面最多只能有一个主键索引;
  • 物理实现方式划分:聚集索引,非聚集索引(二级索引或者辅助索引)
    聚集索引:可以按照主键来排序存储数据,在查找行的时候非常有效,一个表只能有一个聚集索引;
    非聚集索引:在数据库系统会有单独的存储空间存放非聚集索引,这些索引项是按照顺序存储的,但是索引项指向的内容是随机的。也就是说系统会进行两次查找,先找到索引,再找到索引对应的位置取出数据行。可以有多个非聚集索引,也就是多个索引目录提供数据检索。
  • 按照字段个数划分:单一索引,联合索引
    单一索引:索引列为一列;
    联合索引:多个列组合在一起创建的索引,联合索引存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配;
  1. 索引的使用
  • 创建表的时候直接指定:
    CREATE TABLE mytable(   
    ID INT NOT NULL,   
    username VARCHAR(16) NOT NULL,  
    INDEX [indexName] (username(length))  
    );  
    
  • 修改表结构:
    ALTER table tableName ADD INDEX indexName(columnName);
    
  • 删除索引:
    DROP  INDEX [indexName] ON mytable;
    
  • 显示索引信息:
    mysql> SHOW INDEX FROM table_name;
    
  1. 创建索引的规律
  • 字段的数值有唯一性的限制;
  • 频繁作为WHERE查询条件的字段,尤其是在数据表大的情况下;
  • 需要经常GROUP BY 和 ORDER BY的列;
  • 多条件联合查询的时候最好创建联合索引;
  • UPDATE,DELETE的WHERE条件列,一般也需要创建索引;
    如果进行更新的时候,更新的字段是非索引字段,提升的效率会更明显,这是因为非索引字段更新不需要对索引进行维护。不过在实际工作中,我们也需要注意平衡,如果索引太多了,在更新数据的时候,如果涉及到索引更新,就会造成负担。
  • DISTINCT字段需要创建索引;
  • 做多表JOIN连接操作时,创建索引需要注意:
    a. 连接表不要超过3张;
    b. 对WHERE条件创建索引,因为WHERE才是对数据条件的过滤;
    c. 对用于连接的字段创建索引,并且该字段在多张表中的类型必须一致;
  1. 不需要创建索引的情况:
  • WHERE 条件(包括 GROUP BY、ORDER BY)里用不到的字段不需要创建索引,索引的价值是快速定位,如果起不到定位的字段通常是不需要创建索引的;
  • 如果表记录太少,比如少于 1000 个,那么是不需要创建索引的;
  • 字段中如果有大量重复数据,也不用创建索引;
  1. 索引失效:
  • 如果索引进行了表达式计算,则会失效;
  • 如果对索引使用函数,也会造成失效;
  • 在 WHERE 子句中,如果在 OR 前的条件列进行了索引,而在 OR 后的条件列没有进行索引,那么索引会失效;
  • 当我们使用 LIKE 进行模糊查询的时候,后面不能是 %;
  • 索引列尽量设置为 NOT NULL 约束;
  • 我们在使用联合索引的时候要注意最左原则,最左原则也就是需要从左到右的使用索引中的字段,一条 SQL 语句可以只使用联合索引的一部分,但是需要从最左侧开始,否则就会失效;
  1. 三星索引标准
    三星索引标准可以让SQL查询效率最大化:
    • 在 WHERE 条件语句中,找到所有等值谓词中的条件列,将它们作为索引片中的开始列;
    • 将 GROUP BY 和 ORDER BY 中的列加入到索引中;
    • 将 SELECT 字段中剩余的列加入到索引片中;
  1. 锁的分类:
  • 按照锁的粒度进行划分:行锁,页锁,表锁
    不同的数据库和存储引擎支持的锁粒度不同:


    image.png
  • 从数据库管理的角度划分:共享锁,拍他锁
    共享锁:也叫做读锁或S锁,共享锁锁定的资源可以被其他用户读取,但是不能修改。在进行select的时候,会将对象进行共享锁锁定。
    //加共享锁
    LOCK TABLE product_comment READ;
    //解锁
    UNLOCK TABLE;
    
    排它锁:也叫做独占锁,写锁或X锁。排他锁锁定的数据只允许进行锁定操作的事务使用,其他事务无法对已锁定的数据进行查询或修改。当我们对数据进行更新的时候,也就是INSERT,DELETE或者UPDATE的时候,数据库也会自动使用排它锁。
    //加排它锁
    LOCK TABLE product_comment WRITE;
    //解锁
    UNLOCK TABLE;
    
    意向锁:就是给更大一级别的空间示意里面是否已经上过锁。比如数据页或数据表加上意向锁,告诉其他人这个数据页或数据表已经有人上过排它锁了,这样当其他人想要获取数据表排它锁的时候,只需要了解是否有人已经获取了这个数据表的意向排他锁即可。
  • 程序员角度划分:乐观锁,悲观锁(这两种锁是两种看待数据并发的思维方式)
    乐观锁:认为对同一数据的并发操作不会总发生,属于小概率事件,不用每次都对数据上锁,也就是不采用数据库自身的锁机制,而是通过程序来实现(版本号机制或者时间戳机制)。乐观锁适合读操作多的场景。
    悲观锁:对诗句被其他事务的修改持保守太大,会通过数据库自身的锁机制来实现,从而保证数据操作的排他性。悲观锁适合写操作多的场景。


    image.png
  1. 死锁
    死锁就是多个事务在执行过程中,因为竞争某个相同的资源而造成阻塞的现象。当死锁发生的时候,就需要一个事务进行回滚,另一个事务获取锁定完成事务,然后将锁释放掉。
    避免死锁的方法:
  • 如果事务涉及多个表,操作比较复杂,那么可以尽量一次锁定所有的资源,而不是逐步来获取;
  • 如果事务需要更新数据表中的大部分数据,数据表又比较大,可以采用锁升级的方式,比如将行锁升级为表锁;
  • 不同事务并发读写多张数据表,可以约定访问表的顺序,采用相同的顺序降低死锁发生的概览;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335