Golang 数据库操作

Golang 数据库 MySQL

Golang支持DB操作位于database包下,支持基本CRUD操作、事务和Prepared Statement,本文以MySQL为例。

MySQL驱动安装 

使用数据库之前,必须安装相关MySQL数据驱动[1],如果未安装驱动或者没有引入驱动库会报以下错误: 

failed to open database: sql: unknown driver "mysql" (forgotten import?) 

安装golang mysql driver 

go get github.com/go-sql-driver/mysql 

代码中还需注册数据库驱动,通过引入空白倒入[2]mysql包来完成

import(

"database/sql"

// 引入数据库驱动注册及初始化

_ "github.com/go-sql-driver/mysql" ) 

这段空白倒入代码实际执行mysql包的初始化代码,位于%GOPATH%/github.com/go-sql-driver/mysql/driver.go

func init() {

    sql.Register("mysql", &MySQLDriver{})

}

准备测试数据 

连接MySQL 

mysql -uroot -p 

选择数据库test 

use test 

创建测试用的users表和order表,并插入测试数据

#创建user表

DROP TABLE IF EXISTS `order`;

DROP TABLE IF EXISTS `user`;

CREATE TABLE IF NOT EXISTS `user` (`uid` SERIAL PRIMARY KEY, `name`
VARCHAR(20) NOT NULL, `password` VARCHAR(20) NOT NULL) ENGINE=`innodb`,
CHARACTER SET=utf8;

#创建order表

CREATE TABLE IF NOT EXISTS `order`(`oid` SERIAL PRIMARY KEY, `uid`
 BIGINT(20) UNSIGNED NOT NULL, `date` TIMESTAMP NOT NULL DEFAULT
CURRENT_TIMESTAMP, FOREIGN KEY (`uid`) REFERENCES
`user`(`uid`))ENGINE=innodb,CHARACTER SET=utf8;

#插入测试数据

INSERT INTO  `user`(`name`,`password`) VALUES('nick', 'nick'),('jacky', 'jacky');

INSERT INTO `order`(`uid`) VALUES(1),(2);

连接数据库 

连接数据的DSN格式为: 

username:password@protocol(address)/dbname?param=value 

示例代码:

db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test?charset=utf8")

    if err != nil {

        fmt.Println("failed to open database:", err.Error())

        return

    }

    if err := db.Ping(); err != nil {

        fmt.Println("%s error ping database: %s", err.Error())

        return

    }

    defer db.Close()

返回的DB对象,实际封装了一个数据库连接池,对于goroutine是线程安全的,可以放心使用。这个数据库连接池由"database/sql"包负责自动创建和回收。连接池的大小可以由SetMaxIdleConns指定。 

需要注意的是,创建DB对象成功,并不代表已经成功的连接了数据库,数据库连接只有在真正需要的时候才会被创建。因此如果,在创建DB对象后想验证数据库连接是否有效,可以调用Ping()或者通过

关闭数据库

defer db.Close()

关闭数据库并释放全部已打开的资源。实际上,很少需要进行关闭操作,DB对象实际上长期存活并在所有的goroutine之间共享

CRUD 

DB中执行SQL通过Exec和Query方法,查询操作是通过Query完成,它会返回一个sql.Rows的结果集,包含一个游标用来遍历查询结果;Exec方法返回的是sql.Result对象,用于检测操作结果,及被影响记录数

查询

// 获取USERS表中的前十行记录

rows, err := db.Query("SELECT * FROM user")

if err != nil {

    fmt.Println("fetech data failed:", err.Error())

    return

}

defer rows.Close()

for rows.Next() {

    var uid int

    var name, password string

    rows.Scan(&uid, &name, &password)

    fmt.Println("uid:", uid, "name:", name, "password:", password)

}

注意:rows必须进行关闭否则会导致数据库连接无法关闭,长时间运行会导致"too many connections" 

插入

// 插入一条新数据

result, err := db.Exec("INSERT INTO `user`(`name`,`password`) VALUES('tom', 'tom')")

if err != nil {

    fmt.Println("insert data failed:", err.Error())

    return

}

id, err := result.LastInsertId()

if err != nil {

    fmt.Println("fetch last insert id failed:", err.Error())

    return

}

fmt.Println("insert new record", id)

更新

// 更新一条数据

result, err = db.Exec("UPDATE `user` SET `password`=? WHERE `name`=?", "tom_new_password", "tom")

if err != nil {

    fmt.Println("update data failed:", err.Error())

    return

}

num, err := result.RowsAffected()

if err != nil {

    fmt.Println("fetch row affected failed:", err.Error())

    return

}

fmt.Println("update recors number", num)

删除

// 删除数据

result, err = db.Exec("DELETE FROM `user` WHERE `name`=?", "tom")

if err != nil {

    fmt.Println("delete data failed:", err.Error())

    return

}

num, err = result.RowsAffected()

if err != nil {

    fmt.Println("fetch row affected failed:", err.Error())

    return

}

fmt.Println("delete record number", num)

事务支持 

sql.Tx用来支持事务处理

// 事务处理

// 完全删除用户编号为2的用户数据

tx, err := db.Begin()

result, err = tx.Exec("DELETE FROM `order` WHERE uid=? ", 2)

if err != nil {

    fmt.Println("delete data failed:", err.Error())

    return

}

num, err = result.RowsAffected()

if err != nil {

    fmt.Println("fetch row affected failed:", err.Error())

    return

}

fmt.Println("delete record number", num)

result, err = tx.Exec("DELETE FROM `user` WHERE uid=? ", 2)

if err != nil {

    fmt.Println("delete data failed:", err.Error())

    return

}

num, err = result.RowsAffected()

if err != nil {

    fmt.Println("fetch row affected failed:", err.Error())

    return

}

fmt.Println("delete record number", num)

// 根据条件回滚或者提交

// tx.Rollback()

tx.Commit()

Prepared Statement 

sql.Stmt支持预备表达式,可以用来优化SQL查询提高性能,减少SQL注入的风险, DB.Prepare()和Tx.Prepare()都提供了对于预备表达式的支持。

// 预备表达式

stmt, err := db.Prepare("DELETE FROM `order` WHERE `oid`=?")

if err != nil {

    fmt.Println("fetch row affected failed:", err.Error())

    return

}

result, err = stmt.Exec(1)

if err != nil {

    fmt.Println("delete data failed:", err.Error())

    return

}

num, err = result.RowsAffected()

if err != nil {

    fmt.Println("fetch row affected failed:", err.Error())

    return

}

fmt.Println("delete record number", num)

GO数据库的更多相关文章

  1. JSP应用开发 -------- 电纸书(未完待续)

    http://www.educity.cn/jiaocheng/j9415.html JSP程序员常用的技术   第1章 JSP及其相关技术导航 [本章专家知识导学] JSP是一种编程语言,也是一种动 ...

  2. nodejs进阶(6)—连接MySQL数据库

    1. 建库连库 连接MySQL数据库需要安装支持 npm install mysql 我们需要提前安装按mysql sever端 建一个数据库mydb1 mysql> CREATE DATABA ...

  3. GreenDao 数据库:使用Raw文件夹下的数据库文件以及数据库升级

    一.使用Raw文件夹下的数据库文件 在使用GreenDao框架时,数据库和数据表都是根据生成的框架代码来自动创建的,从生成的DaoMaster中的OpenHelper类可以看出: public sta ...

  4. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库

    在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...

  5. Java MyBatis 插入数据库返回主键

    最近在搞一个电商系统中由于业务需求,需要在插入一条产品信息后返回产品Id,刚开始遇到一些坑,这里做下笔记,以防今后忘记. 类似下面这段代码一样获取插入后的主键 User user = new User ...

  6. 在SQL2008查找某数据库中的列是否存在某个值

    在SQL2008查找某数据库中的列是否存在某个值 --SQL2008查找某数据库中的列是否存在某个值 create proc spFind_Column_In_DB ( @type int,--类型: ...

  7. 分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间)

    分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间) 很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间 这里共享一个脚本 CREATE TABLE #tab ...

  8. SQL Server2014 SP2新增的数据库克隆功能

    SQL Server2014 SP2新增的数据库克隆功能 创建测试库 --创建测试数据库 create database testtest use testtest go --创建表 )) --插入数 ...

  9. 数据库优化案例——————某市中心医院HIS系统

    记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...

  10. NoSql数据库使用半年后在设计上面的一些心得

    NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...

随机推荐

  1. 八大排序算法之二希尔排序(Shell Sort)

    希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进.希尔排序又叫缩小增量排序 基本思想: 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录 ...

  2. SDUT 2608:Alice and Bob

    Alice and Bob Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Alice and Bob like playing ...

  3. Improving the GPA 分类: 贪心 HDU 比赛 2015-08-08 16:12 11人阅读 评论(0) 收藏

    Improving the GPA Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) ...

  4. Uva 1626,括号序列

    题目链接:https://uva.onlinejudge.org/external/16/1626.pdf 题意: 给定一个字符串,看是否括号匹配,不匹配加括号,加最少的括号使得匹配.输出该结果. 分 ...

  5. jquery简单插件到复杂插件(2)--简单手风琴

    手风琴就是展示与隐藏 <div id="dataContent"> <div class="dataLeft fl"> <div ...

  6. MySQL基础(四)——索引

    MySQL基础(四)--索引

  7. dual,rowid,rownum

    一. dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情,如下: 1.查看当前用户,可以在 SQL Plus中执行下面语句 s ...

  8. iOS深入学习(UITableView:系列1-最基本的东西)

    这是UITableView博客系列的第一篇,使用xib和arc编码,主要讲解一些UITableView使用过程中简单的.但是又容易被忽略的东西,而且我会告诉读者,怎样在使用了之后就再也不会忘记. 操作 ...

  9. 如何使用NUnit

    http://www.c-sharpcorner.com/UploadFile/84c85b/nunit-with-C-Sharp/ 从github上下载安装包 NUnit.3.4.1.msi htt ...

  10. Set Font Properties On Mouse Hover Of Push Button And Text Items At Run time In Oracle Forms

    Change the font size and weight of text items and push buttons on mouse hover in Oracle Forms.   An ...