19年底36周:Go database/sql库-Go数据库操作

一、简介

  1. database/sql提供了Go访问和操作SQL数据库的方法。
  2. 在Go语言中,使用sql.DB使用此类型来创建语句和事务,并执行查询以及获取结果。
  3. sql.DB负责的是:
    • 负责通过驱动程序打开和关闭与实际底层数据库的连接;
    • 负责管理连接池(但不负责回收,需要开发者自己回收);

二、数据库操作

  1. 数据库连接:连接仅仅是对数据库抽象,并没有真正连接。需要通过db.Ping()来测试连接。
  2. 不同数据库的查询语句占位符:
    • Mysql:?
    • Postgresql: $N,其中N为数字
    • SQLite:接受上述两者之一
    • Oracle::paramN
  3. 基本命令:
    Open() – creates a DB
    Close() - closes the DB
    Query() - 查询
    QueryRow() -查询行
    Exec() -执行操作,update,insert,delete
    Row - A row is not a hash map, but an abstraction of a cursor
    Next()
    Scan()
    Prepare() - 准备语句
  4. 数据库的基本操作逻辑:准备、执行、关闭
  5. 数据库的操作主要分为两个:Exec(),Query()
  • 如何使用Query()
  1. 使用db.Query()来发送查询到数据库,获取结果集Rows,并检查错误。
  2. 使用rows.Next()作为循环条件,迭代读取结果集。
  3. 使用rows.Scan从结果集中获取一行结果。
  4. 使用rows.Err()在退出迭代后检查错误。
  5. 使用rows.Close()关闭结果集,释放连接。
func dbPrepare(db sql.DB){
    stmt, err := db.Prepare("select id, name from users where id != ?")
    // stmt是一个支持高并发的预备sql, 当stmt关闭后,那么后面的所有使用stmt的都不可以使用
    // 准备、执行、关闭
    if err != nil {
        log.Fatal(err)
    }
    defer stmt.Close()
    rows, err := stmt.Query(1) // 1, stmt.Query() 发送查询到数据库获取结果集
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close() // 5, rows.Close() 延迟关闭结果集,释放连接
    for rows.Next() { // 2, rows.Next() 循环迭代结果集
        err := rows.Scan(&id, &name) // 3, rows.Scan() 读取一行数据,这个是从远程一行行读取的还是本地缓存? 
        processErr(err)
        log.Println(id,name)
    }
    // 4, rows.Err() 在退出迭代后检查错误
    if err = rows.Err(); err != nil {
        log.Fatal(err)
    }
}

  1. 准备语句Prepared Statement
  • 一个stmt对应着一个数据库连接.
  • stmt 会记住它一个最近使用过的连接,如果这个连接已经被用了,那么它会新建一个stmt和重新获取一个连接。
  • 上述的方式会导致大量的高并发连接和泄漏,重连的次数超乎想象,结果就你懂得。
  • 有时候纯文本查询 a plaintext query 效率可能会更好(如果一个prepared statement 能够被多次执行,那么用它。否则还是直接手写ok。
  • 此外,Mysql数据库不建议使用prepared statement
  • 以上原因参考:An example of this can be seen at the [图片上传失败...(image-6033f3-1570439040218)] blog.

三、使用sql.DB注意事项

  1. 把sql.DB视为长期存在的对象,否则可能会遇到诸如重复使用和连接共享不足;
  2. 使用db.Query(sqlStr, sqlDatas)和db.Prepare(sqlStr).Exec(sqlDatas)的区别:
  • 答:本质上没区别?Prepare once,execute many times,对于批量操作的时候用这个?
  1. 增删改等doesn’t return rows的操作使用 Exec()[并且配套使用prepared statement], 查询使用 Query()。
  • 答:使用Query但不读取返回结果,会导致底层连接永远无法释放。
    [图片上传失败...(image-1c045c-1570439040218)]
  1. 查询时一定要释放连接defer rows.Close()

你可能感兴趣的:(19年底36周:Go database/sql库-Go数据库操作)