美文网首页
19年底36周:Go database/sql库-Go数据库操作

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

作者: 习惯研究所所长 | 来源:发表于2019-10-07 17:04 被阅读0次

    一、简介

    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数据库操作

          本文链接:https://www.haomeiwen.com/subject/jpblyctx.html