iOS數(shù)據(jù)庫-Sqlite

1 SQLite

數(shù)據(jù)庫的SQL語句分為三種分別是:DDL DML DQL

1.1 約束關(guān)鍵字

常見約束關(guān)鍵字(不區(qū)分大小寫):

if not exists  如果不存在
if exists 如果存在
primary key 主鍵
autoincrement 自增
not null 不能為空
default 默認(rèn)值

常見數(shù)據(jù)庫數(shù)據(jù)類型

integer 整型
text 文本
real 浮點(diǎn)型

1.2 DDL語句

DDL語句一般是用來操作數(shù)據(jù)表的渗柿,對數(shù)據(jù)表進(jìn)行定義萝究、刪除和修改操作的。對應(yīng)的關(guān)鍵字分別為:create/drop/alter

SQL語句示例

//1 創(chuàng)建數(shù)據(jù)表(創(chuàng)建學(xué)生表t_student)
create table if not exists t_student(id integer primary key autoincrement,name text not null,age integer,score real default 60)

//2 刪除數(shù)據(jù)表 (刪除學(xué)生表t_student)
drop table if exists s_student

//3 修改數(shù)據(jù)表
//--3.1 修改數(shù)據(jù)表的名稱
alter table t_student rename to t_person
//--3.2 增加數(shù)據(jù)表字段
alter table t_stu add column telephone integer

1.3 DML語句

DML語句一般是用來操作數(shù)據(jù)表中的記錄的。對數(shù)據(jù)表的記錄進(jìn)行增刪改操作通稱為DML語句

SQL語句示例

//1 插入記錄
insert into t_stu(name,age,score) values('chmn',24,100)

//2 刪除記錄
delete from t_stu where name = 'chmn'
delete from t_stu where name is 'chmn'

//3 修改記錄
update t_stu set score = 99 where name = 'chmn'

1.4 DQL語句

該語句就是對數(shù)據(jù)表字段進(jìn)行查詢操作顶伞,可以多表查詢

<b style="color:red">
注意:

比如說逆趣,有一個學(xué)生表和一個分?jǐn)?shù)表。學(xué)生表里面的學(xué)號是固定的膝蜈,是學(xué)生表的主鍵鹅心。分?jǐn)?shù)表中也有一個No,它的取值由學(xué)生表里面的學(xué)號字段決定吕粗,那么就需要在分?jǐn)?shù)表中設(shè)置外鍵,外鍵為學(xué)生表的學(xué)號

</b>

SQL語句示例

//1 查詢所有
select * from t_stu
//2 多表查詢
select * from t_stu,t_score where t_stu.no = t_score_no
//3 排序order by 
select * from t_score order by score DESC  降序
//4 統(tǒng)計count average min max
select count(*) from t_score 
select sum(score) from t_score 

//5 分頁limit
select * from t_score limit 1,2   //跳過1條旭愧,取2條
select * from t_score limit 3 //跳過0條颅筋,取3條

2 代碼實現(xiàn)SQL語句

2.1 實現(xiàn)大致步驟

  • 導(dǎo)入框架sqlite3.tdb,導(dǎo)入頭文件sqlite3.h
  • 創(chuàng)建并打開數(shù)據(jù)庫 (sqlite3_open)
  • 執(zhí)行sql語句 (sqlite3_exec)

2.2 代碼實現(xiàn)DDL語句

點(diǎn)擊屏幕后,打開數(shù)據(jù)庫并創(chuàng)建數(shù)據(jù)表t_person

    //1 打開數(shù)據(jù)庫
    //--1.1 數(shù)據(jù)庫路徑(后綴名任意输枯,一般為sqlite或者db)
    let path = "/Users/apple/Pictures/myDb.sqlite"
    //--1.2 定義數(shù)據(jù)庫指針议泵,用來指向打開的數(shù)據(jù)庫
    var db:COpaquePointer = nil
    //--1.3 打開數(shù)據(jù)庫(如果該路徑不存在,則創(chuàng)建后打開)
    if sqlite3_open(path, &db) == SQLITE_OK {
        print("數(shù)據(jù)庫打開成功")
    }else {
        print("數(shù)據(jù)庫打開失敗")
    }
    
    
    //2 創(chuàng)建數(shù)據(jù)表
    //--2.1 獲取SQL語句
    let sql = "create table if not exists t_person(name text,age integer)"
    //--2.2 執(zhí)行sql語句
    /*
      參數(shù)1 打開的數(shù)據(jù)庫
      參數(shù)2 執(zhí)行的sql語句
      參數(shù)3 回調(diào)
      參數(shù)4 回調(diào)的參數(shù)
      參數(shù)5 錯誤信息
    */
    if sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK {
        print("數(shù)據(jù)表創(chuàng)建成功")
    }else{
        print("數(shù)據(jù)表創(chuàng)建失敗")
    }
    
    
    //3 刪除數(shù)據(jù)表
    let deleSql = "drop table if exists t_person"
    if sqlite3_exec(db, deleSql, nil, nil, nil) == SQLITE_OK {
        print("刪除表創(chuàng)建成功")
    }else{
        print("刪除表創(chuàng)建失敗")
    }

一般將其進(jìn)行封裝成工具類桃熄,直接使用

封裝的工具類 SqliteTool.swift

class SqliteTool: NSObject {


//設(shè)置單例
static let shareInstance = SqliteTool()

//定義數(shù)據(jù)庫指針先口,用來指向打開的數(shù)據(jù)庫
var db:COpaquePointer = nil

override init() {
    super.init()
    /**打開數(shù)據(jù)庫*/
    
     //1 打開數(shù)據(jù)庫
    let path = "/Users/apple/Pictures/myDb.sqlite"
    //打開數(shù)據(jù)庫(如果該路徑不存在,則創(chuàng)建后打開)
    if sqlite3_open(path, &db) == SQLITE_OK {
        print("數(shù)據(jù)庫打開成功")
        
    }else {
        print("數(shù)據(jù)庫打開失敗")
    }
}

/**執(zhí)行sql語句*/
func execute(sql:String) -> Bool
{
    return (sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK)
}
     
/**創(chuàng)建table*/
func createTable()
{
    //獲取SQL語句
    let sql = "create table if not exists t_person(name text,age integer)"
    //執(zhí)行sql語句
    /*
    參數(shù)1 打開的數(shù)據(jù)庫
    參數(shù)2 執(zhí)行的sql語句
    參數(shù)3 回調(diào)
    參數(shù)4 回調(diào)的參數(shù)
    參數(shù)5 錯誤信息
    */
    if execute(sql){
        print("創(chuàng)建table成功")
    }else{
        print("創(chuàng)建table失敗")
    }
}


/**刪除table*/
func dropTable()
{
    //刪除數(shù)據(jù)表
    let sql = "drop table if exists t_person"
    if execute(sql){
        print("刪除table成功")
    }else{
        print("刪除table失敗")
    }
       
}
 

}

2.3 代碼實現(xiàn)DML語句

定義Person類蜻拨,有姓名和年齡兩個字段池充,將這個這個實例對象插入到上述的數(shù)據(jù)表中,做更新等操作

Person.swift增加以下對象方法

2.3.1 插入

/**插入到數(shù)據(jù)表*/
func insertTable()
{
    //1 常見sql
    let sql = "insert into t_person(name,age) values('\(self.name)',\(self.age))"
    //2 執(zhí)行sql語句
    if SqliteTool.shareInstance.execute(sql) {
        print("插入成功")
    }else{
        print("插入失敗")
    }
}

2.3.2 刪除

/**從數(shù)據(jù)表中刪除*/
func deleteFromTable()
{
    let sql = "delete from t_person where name = '\(self.name)'"
    
    if SqliteTool.shareInstance.execute(sql){
        print("刪除成功")
    }else{
        print("刪除失敗")
    }
    
}

2.3.3 修改

func updateTable()
{
    let sql = "update t_person set name = '\(self.name)',age = \(self.age)"
    if SqliteTool.shareInstance.execute(sql){
        print("更新成功")
    }else{
        print("更新失敗")
    }

}

2.3.4 綁定插入

  • 到這里缎讼,我們所使用的插入都是直接使用的sqlite_exec方法實現(xiàn)的。其實坑匠,iOS提供了預(yù)處理語句來綁定插入血崭。而且,上面的sqlite_exec其實是對綁定插入的一次封裝。
  • 綁定插入夹纫,其實就是首先提供預(yù)處理語句咽瓷,然后再綁定預(yù)處理語句中的參數(shù),實現(xiàn)插入
  • 一般地舰讹,綁定插入比直接使用sqlite_exec的效率高茅姜,因為sqlite_exec也是對綁定插入進(jìn)行的封裝

綁定插入的步驟

1、 創(chuàng)建sql語句月匣,參數(shù)用問號?表示

2 钻洒、根據(jù)sql創(chuàng)建預(yù)處理語句 sqlite3_prepare_v2

3、 分別綁定參數(shù) sqlite3_bind_text sqlite3_bind_int sqlite3_bind_Double

4锄开、 執(zhí)行預(yù)處理語句 sqlite3_step

5素标、 重置預(yù)處理語句 sqlite3_reset

6、 釋放預(yù)處理語句 sqlite3_finalize

<b style = "color:red">
一般用法:如果在大量數(shù)據(jù)插入中萍悴,1/2/7步只需要執(zhí)行一次头遭,中間循環(huán)執(zhí)行3~6步驟,這樣可以提高效率
</b>

/**綁定插入*/
func bindInsert()
{
    //1 創(chuàng)建預(yù)處理語句--可變參數(shù)用 癣诱?表示计维,固定寫法
    let db = SqliteTool.shareInstance.db //打開的數(shù)據(jù)庫
    let zSql = "insert into t_person(name,age,score) values(?,?,?)" //sql語句
    var ppStmt : COpaquePointer = nil //生成的處理語句-傳入地址
    //-參數(shù)4 ,取出字符串zSql的長度。-1表示自動計算
    //-參數(shù)5 ,表示zSql除去參數(shù)3指定的長度后剩下的語句
    if sqlite3_prepare_v2(db, zSql, -1, &ppStmt, nil) != SQLITE_OK {
        print("預(yù)處理失敗")
    }
    
    
    //2 綁定整型
    //-參數(shù)1撕予,表示上面創(chuàng)建好的預(yù)編譯語句
    //-參數(shù)2享潜,表示綁定zSql中的哪個問號表示的參數(shù),是索引嗅蔬。從1開始的
    //-參數(shù)3剑按,對應(yīng)參數(shù)2的值
    sqlite3_bind_int(ppStmt, 2, 24)  //綁定age = 24
    
    //3 綁定浮點(diǎn)型
    sqlite3_bind_double(ppStmt, 3, 89.7) //綁定score = 89.7
    
    //4 綁定文本類型
    //-參數(shù)1 預(yù)處理語句
    //-參數(shù)2 綁定的索引
    //-參數(shù)3 需要綁定的值
    //-參數(shù)4 從參數(shù)3中取出多長的數(shù)據(jù)進(jìn)行綁定,-1表示自動計算
    //-參數(shù)5 對參數(shù)值的處理方法澜术,有以下兩種
    //-------SQLITE_STATIC :認(rèn)為參數(shù)是一個常量艺蝴,不會被釋放,不會做任何的引用 宏 0
    //-------SQLITE_TRANSIENT:會對參數(shù)進(jìn)行引用 它是一個宏鸟废,-1
    //-------進(jìn)行按位轉(zhuǎn)換猜敢,可以進(jìn)入頭文件查看,因為swift是不能有宏的盒延,所以要自己轉(zhuǎn)換
    //-------將該宏表示的-1轉(zhuǎn)換成sqlite3_destructor_type類型
    let SQLITE_TRANSIENT = unsafeBitCast(-1, sqlite3_destructor_type.self)
    sqlite3_bind_text(ppStmt, 1, "zhangsan", -1, SQLITE_TRANSIENT)
    
    
    
    //5 執(zhí)行預(yù)處理語句
    if sqlite3_step(ppStmt) == SQLITE_DONE {
        print("執(zhí)行成功")
    }else {
        print("執(zhí)行失敗")
    }
    
    
    //6 重置預(yù)處理語句-重置綁定
    sqlite3_reset(ppStmt)
    
    //7 釋放預(yù)處理語句
    sqlite3_finalize(ppStmt)
}

2.3.5綁定插入(sqlite3_step)與插入(sqlite3_exec)的效率分析

測試方法:

當(dāng)前執(zhí)行時刻的獲取方法 CFAbsoluteTimeGetCurrent()

1 使用綁定插入循環(huán)插入10000條數(shù)據(jù)缩擂,計算插入開始和完成的時間差

測試中,循環(huán)執(zhí)行上面代碼的3~6步添寺,計算時間差

2 創(chuàng)建插入sql,使用sqlite3_exec插入胯盯,計算時間差

3 比較兩個效率

結(jié)論:

效率差別有,但不是很大计露。整體插入大數(shù)據(jù)都會出現(xiàn)時間很長的情況博脑,亟待優(yōu)化

2.3.6 大數(shù)據(jù)插入的優(yōu)化

問題的原因

不管是綁定預(yù)處理執(zhí)行(sqlite3_step)還是直接sql執(zhí)行(sqlite3_exec)憎乙,當(dāng)進(jìn)行大數(shù)據(jù)操作的時候,都會出現(xiàn)耗時很長的情況叉趣。其原因:

1 sqlite3_exec是對sqlite3_step的封裝泞边,效率會低

2 sqlite3_step綁定時,雖然創(chuàng)建預(yù)處理語句疗杉,釋放預(yù)處理語句都只執(zhí)行一次阵谚。但是,在每次執(zhí)行數(shù)據(jù)庫操作前烟具,都會首先開啟一個“事務(wù)”梢什,執(zhí)行完一個操作后,提交一個“事務(wù)”净赴。循環(huán)執(zhí)行大量操作時绳矩,開啟事務(wù)和提交事務(wù)的過程會耗時非常大,這才是根本原因

優(yōu)化方法

1 使用綁定操作sqlite3_step

2 創(chuàng)建預(yù)處理語句和釋放預(yù)處理語句都保證只執(zhí)行一次

3 手動開啟事務(wù)和提交事務(wù)

代碼

在綁定參數(shù)之前玖翅,手動開啟事務(wù)

let sql = "begin transaction"
sqlite3_exec(sql)

在結(jié)束插入翼馆,釋放預(yù)處理語句之前,手動提交事務(wù)

let sql = "commit transaction"
sqlite3_exec(sql)

2.4 代碼實現(xiàn)DQL語句

查詢操作也分為兩種金度,一種是直接使用sqlite3_exec執(zhí)行sql語句查詢应媚;另一種是使用sqlite3_step執(zhí)行預(yù)處理語句查詢

2.4.1 sqlite3_exec直接執(zhí)行sql查詢

此時就需要使用到了sqlite3_exec的回調(diào)方法了,每查詢到一行就調(diào)用回調(diào)方法猜极,直到回調(diào)方法返回1或者直到查詢完成中姜,回調(diào)方法中的參數(shù)分別為

  • 參數(shù)1 無意義,由slite3_exec的參數(shù)4傳入的跟伏,類似于上下文之類的
  • 參數(shù)2 查詢到當(dāng)前行的列數(shù)(字段的個數(shù))
  • 參數(shù)3 查詢到當(dāng)前行的字段值的數(shù)組 --- sqlite3_exec方法查詢到所有字段值都當(dāng)做文本類型
  • 參數(shù)4 查詢到當(dāng)前行的字段名稱數(shù)組
  • 返回值 表示是否終止查詢丢胚,我們自行控制。如果返回0受扳,表示一直查詢直到完全查出携龟;如果返回1,表示查詢終止勘高,不再查詢了

舉例:

func queryAll()
{
    //1 創(chuàng)建sql語句
    let sql = "select * from t_person"
    let db = SqliteTool.shareInstance.db //打開的數(shù)據(jù)庫
    //2 執(zhí)行查詢語句 -- 每查詢到一行數(shù)據(jù)就會調(diào)用這個回調(diào)方法
    sqlite3_exec(db, sql, { (firstValue, columnCount, columnValues, columnNames) -> Int32 in
        
        // 遍歷當(dāng)前行的所有字段(列)
        let count = Int(columnCount)
        for i in 0..<count {
            
            // 獲取當(dāng)前的列名(字段名)
            //---類型UnsafeMutablePointer<Int8>相當(dāng)于UnsafeMutablePointer<CChar> ,也相當(dāng)于char * 指向字符串
            let columnName = columnNames[i]
            //---轉(zhuǎn)換成字符串
            let columnNameStr = String(CString: columnName, encoding: NSUTF8StringEncoding)
            
            // 獲取當(dāng)前字段的值
            let columnValue = columnValues[i]
            let columnValues = String(CString: columnValue, encoding: NSUTF8StringEncoding)
            
            print(columnNameStr,columnValues)
            
        }
        return 0 //如果返回0峡蟋,就表示一直查詢,直到查詢結(jié)束华望;如果返回1蕊蝗,表示到當(dāng)前位置終止查詢
        
        }, nil, nil)
}

2.4.2 sqlite3_step執(zhí)行預(yù)處理語句查詢

主要步驟與綁定插入的步驟一樣,首先要創(chuàng)建預(yù)處理語句赖舟,再次綁定語句蓬戚,然后執(zhí)行語句,其次重置語句建蹄,最后釋放語句碌更。

執(zhí)行的結(jié)果集需要我循環(huán)獲取裕偿,它拿到的結(jié)果集是不僅僅是文本型洞慎,可以根據(jù)數(shù)據(jù)庫存儲的實際類型進(jìn)行解析

舉例:

func prepareQuaryAll()
{
    
    let sql = "select * from t_person"
    let db = SqliteTool.shareInstance.db
    var stmt : COpaquePointer = nil
    // 創(chuàng)建預(yù)處理語句
    if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK {
        print("預(yù)處理失敗")
        return
    }
    
    
    
    // 綁定 - 如果沒有需要綁定的參數(shù)痛单,可以省略
    
    // 執(zhí)行預(yù)處理語句 -- 每執(zhí)行一次就是一行數(shù)據(jù),每行記錄(結(jié)果集)都放在stmt中
    while sqlite3_step(stmt) == SQLITE_ROW {
        
        // 獲取當(dāng)前行有多少列(字段)
        let columnCount = sqlite3_column_count(stmt)
        
        // 循環(huán)取出每個字段
        for i in 0..<columnCount {
            // 獲取當(dāng)前字段的字段名稱(當(dāng)前索引劲腿,第幾個字段)
            let columnName = sqlite3_column_name(stmt, i)
            let columnNameStr = String(CString: columnName, encoding: NSUTF8StringEncoding)
            
            
            // 獲取當(dāng)前字段的類型
            let type = sqlite3_column_type(stmt, i)
            
            // 根據(jù)類型取出對應(yīng)類型的值
            if type == SQLITE_TEXT { //如果是文本類型
                let value = sqlite3_column_text(stmt, i)
                let valueInt8 = UnsafePointer<CChar>(value)
                let valueStr = String(CString: valueInt8, encoding: NSUTF8StringEncoding)
                print(columnNameStr,valueStr)
            }else if type == SQLITE_INTEGER{ //如果是整型
                let value = sqlite3_column_int(stmt, i)
                print(columnNameStr,value)
            }else if type == SQLITE_FLOAT { //如果是浮點(diǎn)型
                let value = sqlite3_column_double(stmt, i)
                print(columnNameStr,value)
            }
        }
    }
    
}

3 事務(wù)Transaction(批量操作的優(yōu)化)

  • 事務(wù)是并發(fā)控制的單位旭绒,是用戶定義的操作序列。事務(wù)里面的操作焦人,要么都做挥吵,要么都不做。
  • 事務(wù)是一個不可分割的工作單位花椭。通過事務(wù)忽匈,可以把邏輯相關(guān)的一些操作綁定在一起
  • 事務(wù)通常以begin transaction開始的;以commit transaction或者rollback transaction結(jié)束的
  • 當(dāng)大量的操作執(zhí)行的時候矿辽,默認(rèn)情況下丹允,每個操作都會開啟一個事務(wù)(成功之后提交事務(wù),失敗后回滾事務(wù))袋倔,頻繁的開啟事務(wù)操作會耗時很大
  • 所有雕蔽,大量操作執(zhí)行的時候,我們將這些操作放在一個事務(wù)中宾娜,整體只開啟一個事務(wù)批狐,成功之后提交事務(wù),失敗之后回滾事務(wù)前塔,提高效率嚣艇。

舉例:把插入的語句放到一個事務(wù)transaction中執(zhí)行

func insertOperation()
{
    //創(chuàng)建插入sql
    let sql1 = "insert into t_stu(name,age) values('chenhua',23)" //該數(shù)據(jù)庫存在
    let sql2 = "insert into t_stu2(name,age) values('lisi',24)"   //該數(shù)據(jù)庫不存在
    
    ///開啟事務(wù)
    SqliteTool.shareInstance.execute("begin transaction")
    
    //執(zhí)行操作
    let result1 = SqliteTool.shareInstance.execute(sql1)
    let result2 = SqliteTool.shareInstance.execute(sql2)
    
    //判斷結(jié)果,處理事務(wù)
    if result1 && result2 {
        print("提交")
        SqliteTool.shareInstance.execute("commit transaction")
    }else{
        print("回滾")
        SqliteTool.shareInstance.execute("rollback transaction")        
}

4 FMDB框架的使用

是一個面向?qū)ο蟮腟QLite框架华弓,對sqlite進(jìn)行了封裝食零。所以在導(dǎo)入框架后,需要添加框架依賴 sqlite3.0.tdb

4.1 創(chuàng)建數(shù)據(jù)庫并打開

    let path = "/Users/apple/Desktop/haha/fmdb.sqlite" 
    // 打開數(shù)據(jù)庫
    let db = FMDatabase(path: path)
    db.open()

4.2 創(chuàng)建數(shù)據(jù)表

    // 創(chuàng)建數(shù)據(jù)表
    let tableSql = "create table if not exists t_student(name text,age integer,score real)"
    if db.executeStatements(tableSql) {
        print("創(chuàng)建數(shù)據(jù)表成功")
    }else {
        print("創(chuàng)建數(shù)據(jù)表失敗")
    }

4.3 更新數(shù)據(jù)(增刪改使用executeUpdate方法)

    // 更新數(shù)據(jù)(增刪改都是用executeUpdate)
    let insertSql = "insert into t_student(name,age,score) values('jim',23,22)"
    if db.executeUpdate(insertSql, withArgumentsInArray: nil) {
        print("插入數(shù)據(jù)成功")
    }else{
        print("插入數(shù)據(jù)失敗")
    }

4.4 查詢數(shù)據(jù)(使用executeQuery方法)

    // 查詢數(shù)據(jù) -- 查詢的結(jié)果都放在結(jié)果集中
    let querySql = "select * from t_student"
    let resultSet = db.executeQuery(querySql, withArgumentsInArray: nil)
    //---循環(huán)取出里面的記錄
    while resultSet.next() {
        // 獲取當(dāng)前行的字段數(shù)(列數(shù))
        let columnCount = resultSet.columnCount()
        // 獲取指定字段的值
        let name = resultSet.stringForColumn("name")
        let age  = resultSet.intForColumn("age")
        let score = resultSet.doubleForColumn("score")
        print(name,age,score)
    }

4.5 執(zhí)行事務(wù)

    // 開啟事務(wù)
    db.beginTransaction()
    
    // 執(zhí)行操作
    let insertSql1 = "insert into t_student(name,age,score) values('jim',23,22)"
    let insertSql2 = "insert into t_student2(name,age,score) values('jim',23,22)"
    let result1 = db.executeUpdate(insertSql1, withArgumentsInArray: nil)
    let result2 = db.executeUpdate(insertSql2, withArgumentsInArray: nil)
    
    // 提交或者回滾事務(wù)
    if result1 && result2
    {
        db.commit()
    }else{
        db.rollback()
    }

4.6 預(yù)處理語句

普通狀態(tài)下一樣该抒,不錯需要使用標(biāo)準(zhǔn)語法 用問號慌洪?代表參數(shù)

4.7 線程安全的操作數(shù)據(jù)庫

不能直接使用FMDataBase開啟db,然后執(zhí)行操作凑保。需要使用FMDatabaseQueue類冈爹,他在回調(diào)block中提供了db

    // 創(chuàng)建數(shù)據(jù)庫隊列
    let dbQueue = FMDatabaseQueue(path: path)
    
    // 在數(shù)據(jù)庫中操作
    dbQueue.inDatabase { (db:FMDatabase!) -> Void in
        
        //使用db執(zhí)行響應(yīng)的增刪改查操作
        db.executeUpdate(sql,nil)
          
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市欧引,隨后出現(xiàn)的幾起案子频伤,更是在濱河造成了極大的恐慌,老刑警劉巖芝此,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件憋肖,死亡現(xiàn)場離奇詭異因痛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)岸更,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門鸵膏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人怎炊,你說我怎么就攤上這事谭企。” “怎么了评肆?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵债查,是天一觀的道長。 經(jīng)常有香客問我瓜挽,道長盹廷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任久橙,我火速辦了婚禮俄占,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘剥汤。我一直安慰自己颠放,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布吭敢。 她就那樣靜靜地躺著碰凶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鹿驼。 梳的紋絲不亂的頭發(fā)上欲低,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天,我揣著相機(jī)與錄音畜晰,去河邊找鬼砾莱。 笑死,一個胖子當(dāng)著我的面吹牛凄鼻,可吹牛的內(nèi)容都是我干的腊瑟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼块蚌,長吁一口氣:“原來是場噩夢啊……” “哼闰非!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起峭范,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤财松,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辆毡,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菜秦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了舶掖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片球昨。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖访锻,靈堂內(nèi)的尸體忽然破棺而出褪尝,到底是詐尸還是另有隱情闹获,我是刑警寧澤期犬,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站避诽,受9級特大地震影響龟虎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沙庐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一鲤妥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拱雏,春花似錦棉安、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鹊汛,卻和暖如春蒲赂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刁憋。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工滥嘴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人至耻。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓若皱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尘颓。 傳聞我的和親對象是個殘疾皇子走触,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

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