GO数据库
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数据库的更多相关文章
- JSP应用开发 -------- 电纸书(未完待续)
http://www.educity.cn/jiaocheng/j9415.html JSP程序员常用的技术 第1章 JSP及其相关技术导航 [本章专家知识导学] JSP是一种编程语言,也是一种动 ...
- nodejs进阶(6)—连接MySQL数据库
1. 建库连库 连接MySQL数据库需要安装支持 npm install mysql 我们需要提前安装按mysql sever端 建一个数据库mydb1 mysql> CREATE DATABA ...
- GreenDao 数据库:使用Raw文件夹下的数据库文件以及数据库升级
一.使用Raw文件夹下的数据库文件 在使用GreenDao框架时,数据库和数据表都是根据生成的框架代码来自动创建的,从生成的DaoMaster中的OpenHelper类可以看出: public sta ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库
在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...
- Java MyBatis 插入数据库返回主键
最近在搞一个电商系统中由于业务需求,需要在插入一条产品信息后返回产品Id,刚开始遇到一些坑,这里做下笔记,以防今后忘记. 类似下面这段代码一样获取插入后的主键 User user = new User ...
- 在SQL2008查找某数据库中的列是否存在某个值
在SQL2008查找某数据库中的列是否存在某个值 --SQL2008查找某数据库中的列是否存在某个值 create proc spFind_Column_In_DB ( @type int,--类型: ...
- 分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间)
分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间) 很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间 这里共享一个脚本 CREATE TABLE #tab ...
- SQL Server2014 SP2新增的数据库克隆功能
SQL Server2014 SP2新增的数据库克隆功能 创建测试库 --创建测试数据库 create database testtest use testtest go --创建表 )) --插入数 ...
- 数据库优化案例——————某市中心医院HIS系统
记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...
- NoSql数据库使用半年后在设计上面的一些心得
NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...
随机推荐
- Winform中如何实现父窗体传递数据到子窗体并刷新子窗体
原理:利用委托和事件,本文将以图文并茂的例子讲述,告诉我们So Easy --------------------------------------------------------------- ...
- weblogic远程调试
修改 bin/startWebLogic.cmd 增加红字部分,其中9999是调试监听端口,然后可以连接这个端口进行远程调试 set JAVA_DEBUG=-Xdebug -Xnoagent -Xru ...
- Android 内存优化 (防Memory Leak)
在之前的 Android 内存管理 &Memory Leak & OOM 分析 中,说到了Android的内存管理相关的原理,也能了解到Android Memory Leak 和 ...
- K - Work 分类: 比赛 2015-07-29 19:13 3人阅读 评论(0) 收藏
K - Work Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Sta ...
- JAVA基础知识之IO——IO流(Stream)的概念
Java IO 流 Java将不同的设备或载体(键盘.文件.网络.管道等)的输入输出数据统称为"流"(Stream),即JAVA的IO都是基于流的. JAVA传统的所有流类型类都包 ...
- Linux crond定时任务
第1章 Crond是什么? Crond是linux系统用来定期执行命令或指定程序任务的一种服务或软件.一般情况下,我们安装完Centos5/6linux操作系统之后,默认便会启动Crond任务调度服务 ...
- hahaha
[问题描述] 小Q对计算几何有着浓厚的兴趣.他经常对着平面直角坐标系发呆,思考一些有趣的问题.今天,他想到了一个十分有意思的题目: 首先,小Q会在x轴正半轴和y轴正半轴分别挑选n个点.随后,他将轴的点 ...
- C语言第3天标准的输入输出函数
:first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; m ...
- HDU2112 HDU Today 最短路+字符串哈希
HDU Today Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- External Storage 数据存储
一些数据存储的封装:http://hubingforever.blog.163.com/blog/static/17104057920129198236599/ External Storage数据存 ...