SQLite3深入淺出

文章目錄:
  1. sqlite3 基礎(chǔ)語(yǔ)句
  2. sqlite3 API
  3. sqlite3 線程安全
  4. FMDB
基礎(chǔ)語(yǔ)句:
  • 創(chuàng)建數(shù)據(jù)庫(kù)文件
    學(xué)習(xí)sqlite3的基礎(chǔ)在于SQL語(yǔ)句质欲,開(kāi)始前請(qǐng)輸入$ sqlite3 驗(yàn)證你的電腦是否已經(jīng)安裝了sqlite3
    首先我們需要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù)庫(kù)文件,打開(kāi)終端驶兜,在合適的目錄下舞丛,輸入:
$ sqlite3 studyDB.db
.databases
  • 創(chuàng)建表
    以id為主鍵并自動(dòng)增加,創(chuàng)建一個(gè)名為book的表:
create table if not exists book (id integer primary key autoincrement, bookNumber integer, bookName text, authorID integer, pressName text);

輸入如下命令查看數(shù)據(jù)表是否創(chuàng)建成功:

.tables
  • insert
    有了數(shù)據(jù)表以后,就可以愉快地寫(xiě)SQL語(yǔ)句來(lái)測(cè)試了走贪,先從基礎(chǔ)的增刪改查開(kāi)始:
    輸入如下指令,向數(shù)據(jù)表中插入一條記錄:
insert into book (bookNumber, bookName, authorID, pressName) values (1001, '三國(guó)演義', 10, '長(zhǎng)江出版社');
  • select
    然后做查詢(xún)操作惑芭,看上一條記錄是否插入成功:
select * from book;

然而在終端練習(xí)SQL語(yǔ)句坠狡,看起來(lái)并不那么清晰,所以接下來(lái)我們用一個(gè)可視化工具MesaSQLite來(lái)練習(xí)SQL語(yǔ)句强衡,解壓之后請(qǐng)閱讀Serial.txt擦秽,如圖:


接下來(lái)我們多插入幾條記錄,以便演示操作:

insert into book (bookNumber, bookName, authorID, pressName) values (1002, '水滸傳', 11, '黃河出版社');
insert into book (bookNumber, bookName, authorID, pressName) values (1003, '西游記', 12, '長(zhǎng)沙出版社');
insert into book (bookNumber, bookName, authorID, pressName) values (1004, '紅樓夢(mèng)', 13, '武漢出版社');
insert into book (bookNumber, bookName, authorID, pressName) values (1005, '瑯琊榜', 14, '黃河出版社');
insert into book (bookNumber, bookName, authorID, pressName) values (1006, '偽裝者', 15, '長(zhǎng)江出版社');
insert into book (bookNumber, bookName, authorID, pressName) values (1007, '簡(jiǎn)愛(ài)', 16, '長(zhǎng)江出版社');
insert into book (bookNumber, bookName, authorID, pressName) values (1008, '大主宰', 14, '武漢出版社');

執(zhí)行以上SQL語(yǔ)句以后漩勤,我們的數(shù)據(jù)表中的數(shù)據(jù)應(yīng)該是這樣的:


  • where
    條件語(yǔ)句where感挥,查詢(xún)bookNumber為1003的記錄:
select  * from book where bookNumber = 1003;
  • update
    修改bookNumber為1002的記錄,然后查詢(xún)所有記錄:
update book set pressName = '清華大學(xué)出版社' where bookNumber = 1002;
select * from book;
  • delete
    刪除紅樓夢(mèng)越败,然后查詢(xún):
delete from book where bookName = '紅樓夢(mèng)';
select *from book;
  • and
    邏輯運(yùn)算符and触幼,查詢(xún)pressName為黃河出版社,并且authorID為14的記錄:
select * from book where pressName = '黃河出版社' and authorID = 14;
  • or
    邏輯運(yùn)算符or究飞,查詢(xún)authorID為14置谦,或者pressName為長(zhǎng)江出版社的記錄:
select * from book where pressName= '長(zhǎng)江出版社' or authorID = 14;
  • like
    模糊查詢(xún)指令like:
select * from book where pressName like '長(zhǎng)%';
select * from book where authorID like '_4';
  • in
    查詢(xún)authorID為14或16的記錄:
select * from book where authorID in (14, 16);
  • not in
    查詢(xún)pressName不為“長(zhǎng)江出版社”的記錄:
select * from book where pressName not in ('長(zhǎng)江出版社');
  • between
    查詢(xún)authorID在14到20之間的記錄:
select * from book where authorID between 14 and 20;
  • count
    查詢(xún)pressName為“長(zhǎng)江出版社”的記錄條數(shù):
select count(pressName) from book where pressName = '長(zhǎng)江出版社';

為了方便演示,我們創(chuàng)建另一個(gè)數(shù)據(jù)表author:

create table if not exists author (id integer primary key autoincrement, authorName text, authorID integer, age integer);

執(zhí)行如下SQL語(yǔ)句:

insert into author (authorName, authorID, age) values ('jack', 21, 45);
insert into author (authorName, authorID, age) values ('dave', 10, 33);
insert into author (authorName, authorID, age) values ('rose', 14, 24);
insert into author (authorName, authorID, age) values ('jim', 16, 56);
insert into author (authorName, authorID, age) values ('ivan', 13, 22);

最后我們的author表中的數(shù)據(jù)應(yīng)該是這樣的:


  • sum
    查詢(xún)所有作者的年齡總和:
select sum(age) from author;
  • avg
    查詢(xún)作者的平均年齡:
select avg(age) from author;
  • max
    查詢(xún)最大的作者年齡:
select max(age) from author;
  • min
    查詢(xún)最小的作者年齡:
select min(age) from author;
  • order by
    查詢(xún)所有的記錄亿傅,并按年齡升序排列:
select * from author order by age asc;

查詢(xún)所有的記錄媒峡,并按年齡降序排列:

select * from author order by age desc;
  • 語(yǔ)句嵌套
    查詢(xún)年齡小于平均年齡的記錄:
select * from author where age < (select avg(age) from author);
  • 多表聯(lián)合查詢(xún)
    查詢(xún)年齡小于平均年齡的作者姓名、圖書(shū)名葵擎、出版社:
select author.authorName, book.bookName, book.pressName from author, book where author.authorID = book.authorID and age< (select avg(age) from author);
sqlite3 API:

要使用sqlite3 API谅阿,需要?導(dǎo)入libsqlite3.tbd,然后#import 就可以使用sqlite了酬滤。
使用的過(guò)程根據(jù)使用的函數(shù)大致分為如下幾個(gè)過(guò)程:

  1. sqlite3_open()
  2. sqlite3_prepare()
  3. sqlite3_step()
  4. sqlite3_column()
  5. sqlite3_finalize()
  6. sqlite3_close()
    這幾個(gè)過(guò)程是概念上的說(shuō)法签餐,而不完全是程序運(yùn)行的過(guò)程,如sqlite3_column()表示的是對(duì)查詢(xún)獲得一行里面的數(shù)據(jù)的列的各個(gè)操作統(tǒng)稱(chēng)盯串,實(shí)際上在sqlite中并不存在這個(gè)函數(shù)氯檐。
  • sqlite3_open
    函數(shù)定義:
SQLITE_API int SQLITE_STDCALL sqlite3_open(
const char *filename,        /* Database filename (UTF-8) */
sqlite3 **ppDb                 /* OUT: SQLite db handle */
);

在操作數(shù)據(jù)庫(kù)之前,首先要打開(kāi)數(shù)據(jù)庫(kù)体捏。這個(gè)函數(shù)打開(kāi)一個(gè)sqlite數(shù)據(jù)庫(kù)文件冠摄,并且返回一個(gè)數(shù)據(jù)庫(kù)連接對(duì)象糯崎。假如這個(gè)要被打開(kāi)的數(shù)據(jù)文件不存在,則一個(gè)同名的數(shù)據(jù)庫(kù)文件將被創(chuàng)建耗拓。如果使用sqlite3_open和sqlite3_open_v2的話拇颅,數(shù)據(jù)庫(kù)將采用UTF-8的編碼方式,sqlite3_open16采用UTF-16的編碼方式乔询。如果sqlite數(shù)據(jù)庫(kù)被成功打開(kāi)(或創(chuàng)建)樟插,將會(huì)返回SQLITE_OK,否則將會(huì)返回錯(cuò)誤碼竿刁。
filename:需要被打開(kāi)的數(shù)據(jù)庫(kù)文件的文件名黄锤,在sqlite3_open和sqlite3_open_v2中這個(gè)參數(shù)采用UTF-8編碼,而在sqlite3_open16中則采用UTF-16編碼食拜。
ppDb:一個(gè)數(shù)據(jù)庫(kù)連接句柄被返回到這個(gè)參數(shù)鸵熟,即使發(fā)生錯(cuò)誤。唯一的異常是如果sqlite不能分配內(nèi)存來(lái)存放sqlite對(duì)象负甸,ppDb將會(huì)被返回一個(gè)NULL值流强。

  • sqlite3_prepare
    函數(shù)定義:
SQLITE_API int SQLITE_STDCALL sqlite3_prepare(
sqlite3 *db,                       /* Database handle */
const char *zSql,               /* SQL statement, UTF-8 encoded */
int nByte,                          /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt,      /* OUT: Statement handle */
const char **pzTail           /* OUT: Pointer to unused portion of zSql */
);

這個(gè)函數(shù)將sql文本轉(zhuǎn)換成一個(gè)準(zhǔn)備語(yǔ)句(prepared statement)對(duì)象,同時(shí)返回語(yǔ)句對(duì)象的句柄呻待。這個(gè)接口需要一個(gè)數(shù)據(jù)庫(kù)連接指針以及一個(gè)要準(zhǔn)備的包含SQL語(yǔ)句的文本打月。它實(shí)際上并不執(zhí)行(evaluate)這個(gè)SQL語(yǔ)句,它僅僅為執(zhí)行準(zhǔn)備這個(gè)sql語(yǔ)句蚕捉。
db:數(shù)據(jù)庫(kù)連接指針奏篙。
zSql:sql語(yǔ)句,使用UTF-8編碼迫淹。
nByte:如果nByte小于0秘通,則函數(shù)取出zSql中從開(kāi)始到第一個(gè)0終止符的內(nèi)容;如果nByte不是負(fù)的敛熬,那么它就是這個(gè)函數(shù)能從zSql中讀取的字節(jié)數(shù)的最大值肺稀。如果nBytes非負(fù),zSql在第一次遇見(jiàn)‘/000/’或‘u000’的時(shí)候終止应民。
pzTail:上面提到zSql在遇見(jiàn)終止符或者是達(dá)到設(shè)定的nByte之后結(jié)束盹靴,假如zSql還有剩余的內(nèi)容,那么這些剩余的內(nèi)容被存放到pZTail中瑞妇,不包括終止符。
ppStmt:能夠使用sqlite3_step()執(zhí)行的編譯好的準(zhǔn)備語(yǔ)句的指針梭冠,如果錯(cuò)誤發(fā)生辕狰,它被置為NULL,如假如輸入的文本不包括sql語(yǔ)句控漠。調(diào)用過(guò)程必須負(fù)責(zé)在編譯好的sql語(yǔ)句完成使用后使用sqlite3_finalize()刪除它蔓倍。

  • sqlite3_step
    函數(shù)定義:
SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*);

這個(gè)過(guò)程用于執(zhí)行有前面sqlite3_prepare創(chuàng)建的準(zhǔn)備語(yǔ)句悬钳。這個(gè)語(yǔ)句執(zhí)行到結(jié)果的第一行可用的位置。繼續(xù)前進(jìn)到結(jié)果的第二行的話偶翅,只需再次調(diào)用sqlite3_setp()默勾。繼續(xù)調(diào)用sqlite3_setp()直到這個(gè)語(yǔ)句完成,那些不返回結(jié)果的語(yǔ)句(如:INSERT聚谁,UPDATE母剥,或DELETE),sqlite3_step()只執(zhí)行一次就返回形导。

  • sqlite3_column
    函數(shù)定義:
SQLITE_API const void* SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*,intiCol);
SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*,intiCol);
SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*,intiCol);
SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*,intiCol);
SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*,intiCol);
SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*,intiCol);
SQLITE_API const unsigned char* SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*,intiCol);
SQLITE_API const void* SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*,intiCol);
SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*,intiCol);
SQLITE_API sqlite3_value* SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*,intiCol);

這個(gè)過(guò)程從執(zhí)行sqlite3_step()執(zhí)行一個(gè)準(zhǔn)備語(yǔ)句得到的結(jié)果集的當(dāng)前行中返回一個(gè)列环疼。每次sqlite3_step得到一個(gè)結(jié)果集的列停下后,這個(gè)過(guò)程就可以被多次調(diào)用去查詢(xún)這個(gè)行的各列的值朵耕。對(duì)列操作是有多個(gè)函數(shù)炫隶,均以sqlite3_column為前綴。
第一個(gè)參數(shù)為從sqlite3_prepare返回來(lái)的prepared statement對(duì)象的指針阎曹。
第二參數(shù)指定這一行中的想要被返回的列的索引伪阶。最左邊的一列的索引號(hào)是0,行的列數(shù)可以使用sqlite3_colum_count()獲得处嫌。

  • sqlite3_finalize
    函數(shù)定義:
SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt);

這個(gè)過(guò)程銷(xiāo)毀前面被sqlite3_prepare創(chuàng)建的準(zhǔn)備語(yǔ)句栅贴,每個(gè)準(zhǔn)備語(yǔ)句都必須使用這個(gè)函數(shù)去銷(xiāo)毀以防止內(nèi)存泄露。

  • sqlite3_exec
    函數(shù)定義:
SQLITE_API int SQLITE_STDCALL sqlite3_exec(
sqlite3*,                                                            /* An open database */
const char*sql,                                                  /* SQL to be evaluated */
int(*callback)(void*,int,char**,char**),                /* Callback function */
void*,                                                                /* 1st argument to callback */
char **errmsg                                                    /* Error msg written here */
);

sqlite3_step 和 sqlite3_exec 都可以用于執(zhí)行SQL語(yǔ)句锰霜,他們的區(qū)別在于后者是sqlite3_prepare()筹误、sqlite3_step() 和 sqlite3_finalize() 的封裝,能讓程序多次執(zhí)行sql語(yǔ)句而不要寫(xiě)許多重復(fù)的代碼癣缅,然后提供一個(gè)回調(diào)函數(shù)進(jìn)行結(jié)果的處理厨剪。
第1個(gè)參數(shù):數(shù)據(jù)庫(kù)連接指針。
第2個(gè)參數(shù):是一條sql語(yǔ)句友存。
第3個(gè)參數(shù):是一個(gè)函數(shù)指針祷膳,當(dāng)這條語(yǔ)句執(zhí)行之后,sqlite3會(huì)去調(diào)用你提供的這個(gè)函數(shù)屡立。
第4個(gè)參數(shù):是你所提供的指針直晨,你可以傳遞任何一個(gè)指針參數(shù)到這里,這個(gè)參數(shù)最終會(huì)傳到回調(diào)函數(shù)里面膨俐,如果不需要傳遞指針給回調(diào)函數(shù)勇皇,可以填NULL。等下我們?cè)倏椿卣{(diào)函數(shù)的寫(xiě)法焚刺,以及這個(gè)參數(shù)的使用敛摘。
第5個(gè)參數(shù):是錯(cuò)誤信息。注意是指針的指針乳愉。sqlite3里面有很多固定的錯(cuò)誤信息兄淫。執(zhí)行sqlite3_exec 之后屯远,執(zhí)行失敗時(shí)可以查閱這個(gè)指針。

  • sqlite3_close
    函數(shù)定義
SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*);

這個(gè)過(guò)程用于關(guān)閉數(shù)據(jù)庫(kù)
代碼演示:

NSString *select_stmt = [NSString stringWithFormat:
@"select * from people where name = \"%@\"",
self.name.text
];
sqlite3_stmt *stmt;
sqlite3_prepare(db,select_stmt.UTF8String,-1,&stmt,NULL);
while(sqlite3_step(stmt) ==SQLITE_ROW) {
NSString*name = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(stmt,1)];
NSString*address = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(stmt,2)];
NSString*age = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(stmt,3)];
self.name.text= name;
self.address.text= address;
self.age.text= age;
}
sqlite3_finalize(stmt);
sqlite3_close(db);

完整的SQLite3 API 代碼戳這里

線程安全

在iOS開(kāi)發(fā)時(shí)捕虽,為了不阻塞主線程慨丐,數(shù)據(jù)庫(kù)訪問(wèn)必須移到子線程中。從3.3.1版本開(kāi)始泄私,SQLite就是線程安全的了房揭。而iOS的SQLite版本沒(méi)有低于這個(gè)版本的:
3.4.0 - iPhone OS 2.2.1
3.6.12 - iPhone OS 3.0 / 3.1
3.6.22 - iPhone OS 4.0
3.6.23.2 - iPhone OS 4.1 / 4.2
3.7.2 - iPhone OS 4.3
3.7.7 - iPhone OS 5.0

SQLite支持3種線程模式:

  • 單線程:禁用所有的mutex鎖,并發(fā)使用時(shí)會(huì)出錯(cuò)挖滤。當(dāng)SQLite編譯時(shí)加了SQLITE_THREADSAFE=0參數(shù)崩溪,或者在初始化SQLite前調(diào)用sqlite3_config(SQLITE_CONFIG_SINGLETHREAD)時(shí)啟用。

  • 多線程:只要一個(gè)數(shù)據(jù)庫(kù)連接不被多個(gè)線程同時(shí)使用就是安全的斩松。源碼中是啟用bCoreMutex伶唯,禁用bFullMutex。實(shí)際上就是禁用數(shù)據(jù)庫(kù)連接和prepared statement(準(zhǔn)備好的語(yǔ)句)上的鎖惧盹,因此不能在多個(gè)線程中并發(fā)使用同一個(gè)數(shù)據(jù)庫(kù)連接或prepared statement乳幸。當(dāng)SQLite編譯時(shí)加了SQLITE_THREADSAFE=2參數(shù)時(shí)默認(rèn)啟用。若SQLITE_THREADSAFE不為0钧椰,可以在初始化SQLite前粹断,調(diào)用sqlite3_config(SQLITE_CONFIG_MULTITHREAD)啟用;或者在創(chuàng)建數(shù)據(jù)庫(kù)連接時(shí)嫡霞,設(shè)置SQLITE_OPEN_NOMUTEX flag瓶埋。

  • 串行:?jiǎn)⒂盟械逆i,包括bCoreMutex和bFullMutex诊沪。因?yàn)閿?shù)據(jù)庫(kù)連接和prepared statement都已加鎖养筒,所以多線程使用這些對(duì)象時(shí)沒(méi)法并發(fā),也就變成串行了端姚。當(dāng)SQLite編譯時(shí)加了SQLITE_THREADSAFE=1參數(shù)時(shí)默認(rèn)啟用晕粪。若SQLITE_THREADSAFE不為0,可以在初始化SQLite前渐裸,調(diào)用sqlite3_config(SQLITE_CONFIG_SERIALIZED)啟用巫湘;或者在創(chuàng)建數(shù)據(jù)庫(kù)連接時(shí),設(shè)置SQLITE_OPEN_FULLMUTEX flag昏鹃。

而這里所說(shuō)的初始化是指調(diào)用sqlite3_initialize()函數(shù)尚氛,這個(gè)函數(shù)在調(diào)用sqlite3_open()時(shí)會(huì)自動(dòng)調(diào)用,且只有第一次調(diào)用是有效的洞渤。

另一個(gè)要說(shuō)明的是prepared statement怠褐,它是由數(shù)據(jù)庫(kù)連接(的pager)來(lái)管理的,使用它也可看成使用這個(gè)數(shù)據(jù)庫(kù)連接您宪。因此在多線程模式下奈懒,并發(fā)對(duì)同一個(gè)數(shù)據(jù)庫(kù)連接調(diào)用sqlite3_prepare_v2()來(lái)創(chuàng)建prepared statement,或者對(duì)同一個(gè)數(shù)據(jù)庫(kù)連接的任何prepared statement并發(fā)調(diào)用sqlite3_bind_*()和sqlite3_step()等函數(shù)都會(huì)出錯(cuò)(在iOS上宪巨,該線程會(huì)出現(xiàn)EXC_BAD_ACCESS而中止)磷杏。這種錯(cuò)誤無(wú)關(guān)讀寫(xiě),就是只讀也會(huì)出錯(cuò)捏卓。安全使用規(guī)則是:沒(méi)有事務(wù)正在等待執(zhí)行的話极祸,所有prepared statement都要被finalized。

調(diào)用sqlite3_threadsafe()可以獲得編譯期的SQLITE_THREADSAFE參數(shù)怠晴。標(biāo)準(zhǔn)發(fā)行版是1遥金,也就是串行模式;而iOS上是2蒜田,也就是多線程模式稿械。

一段存在線程安全隱患的代碼:


iOS上的SQLite默認(rèn)是多線程模式,多個(gè)線程同時(shí)使用同一個(gè)數(shù)據(jù)庫(kù)連接對(duì)象冲粤,將會(huì)產(chǎn)生異常美莫,解決辦法的一種就是在sqlite3_open前加上sqlite3_config(SQLITE_CONFIG_SERIALIZED)。
完整的線程安全代碼戳這里

MFDB

一個(gè)使用FMDB的代碼示例戳這里
需要說(shuō)明的是 FMDatabaseQueue 解決了線程安全問(wèn)題

參考鏈接:
SQLite教程
sqlite3簡(jiǎn)介
SQLite在多線程環(huán)境下的應(yīng)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末梯捕,一起剝皮案震驚了整個(gè)濱河市厢呵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌傀顾,老刑警劉巖襟铭,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異短曾,居然都是意外死亡寒砖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)错英,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)入撒,“玉大人,你說(shuō)我怎么就攤上這事椭岩∶┐” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵判哥,是天一觀的道長(zhǎng)献雅。 經(jīng)常有香客問(wèn)我,道長(zhǎng)塌计,這世上最難降的妖魔是什么挺身? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮锌仅,結(jié)果婚禮上章钾,老公的妹妹穿的比我還像新娘墙贱。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著远荠,像睡著了一般刮便。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼剖淀。 笑死,一個(gè)胖子當(dāng)著我的面吹牛纤房,可吹牛的內(nèi)容都是我干的纵隔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼帆卓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼巨朦!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起剑令,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤糊啡,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后吁津,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體棚蓄,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年碍脏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了梭依。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡典尾,死狀恐怖役拴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钾埂,我是刑警寧澤河闰,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站褥紫,受9級(jí)特大地震影響姜性,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜髓考,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一部念、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦儡炼、人聲如沸妓湘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)多柑。三九已至,卻和暖如春楣责,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背聂沙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工秆麸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人及汉。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓沮趣,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親坷随。 傳聞我的和親對(duì)象是個(gè)殘疾皇子房铭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容