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. string xml json格式区别

    string 是一种最普通的储存一串字符的数据格式 xml 是一种可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 它非常适合万维网传输,提供统一的方 ...

  2. YTU 2344: 先序遍历二叉树

    原文链接:https://www.dreamwings.cn/ytu2344/2603.html 2344: 先序遍历二叉树 时间限制: 1 Sec  内存限制: 128 MB 提交: 4  解决:  ...

  3. WPF中viewmodel层怎样得到view层的TabControl控件对象?

    View层: <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns: ...

  4. U3D UGUI学习1 - 层级环境

    就像主动碰撞检测需要刚体,刚体需要Mesh Filter.Unity的一些组件都需要基础配置. UGUI的基础配置和NGUI差不多,把NGUI的那些中间件全部削减干净,甚至连快捷键也没有. 1.基础层 ...

  5. 小扩展大用处,自己扩展一个ForeachRead吧

    是否用过IList的扩展方法 Foreach,而郁闷IEnumerable没有这个扩展?(没用过??用用吧,真的很方便,可以少好几行呢!!) 是否为了有一个索引而不得不用 for 而不能用 forea ...

  6. 复旦大学2014--2015学年第一学期高等代数I期末考试情况分析

    一.期末考试成绩班级前几名 金羽佳(92).包振航(91).陈品翰(91).孙浩然(90).李卓凡(85).张钧瑞(84).郭昱君(84).董麒麟(84).张诚纯(84).叶瑜(84) 二.总成绩计算 ...

  7. .Net文件*夹*操作

    一.文件夹操作 Directory类,DirectoryInfo类.使用using System.IO命名空间 (一)创建文件夹 方法一: private string path = @"F ...

  8. 【leetcode❤python】172. Factorial Trailing Zeroes

    #-*- coding: UTF-8 -*-#给定一个整数N,那么N的阶乘N!末尾有多少个0? 比如:N=10,N!=3628800,N!的末尾有2个0.#所有的尾部的0可以看做都是2*5得来的,所以 ...

  9. CodeForces 496B Secret Combination

    Secret Combination Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u ...

  10. linux 查找替换

    esc:   命令模式与插入模式的切换 一.vi查找:    当你用vi打开一个文件后,因为文件太长,如何才能找到你所要查找的关键字呢?在vi里可没有菜单-〉查找, 不过没关系,你在命令模式下敲斜杆( ...