之所以连接orcale比较麻烦是因为orcale并没有提供golang的驱动,所以并不能像java那样引入个驱动包就能连接,也不能像MysqL之类的开源数据库可以自己实现驱动。不过正所谓天无绝人之路,既然纯go实现不了,那么还可以用cgo实现,c语言总该支持了吧。
网上有很多方法,不过都是使用oci实现的,这里我们使用go-oci8(https://github.com/wendal/go-oci8)
一、安装MinGW
首先我们先来配置环境,由于cgo需要gcc支持,所以需要配置gcc环境,如果是linux下一般可以跳过该步骤,win下则需要自己安装了,这里我们使用 MinGW ,可以到官网现下载,不过官网直接提供的安装程序需要安装时联网下载,很可能会失败,所以几经搜索之后找到如下网址: 里边详细介绍了 MinGW各版本的不同,可根据自己情况下载,由于我是64位,这里下载 64位的POSIX版本 。具体的安装过程就不费话了,直接解压即可。
二、安装OCI
由于没有对应驱动包,我们不能直接连接,所以需要通过orcale提供OCI接口(有点像odbc),里边包含需要的类库。下载直接官网就行,找到系统对应版本:- oci下载地址:http://www.oracle.com/technetwork/topics/winsoft-085727.html
在instantclient_11_1下建立\network\admin\目录,添加tnsnames.ora(这个就不解释了吧),内容根据自己的orcale设置。
三、配置go-oci8
直接go getgithub.com/wendal/go-oci8(报错不用管),然后到go\src\github.com/wendal\go-oci8\windows下,将pkg-config.exe拷贝到MinGW\bin下,将oci8.pc复制到MinGW\lib\pkg-config\下,并且编辑oci8.pc:
- # Package Information for pkg-config
- prefix=修改为instantclient_11_1目录,如F:/dev/instantclient_11_1
- exec_prefix=修改为instantclient_11_1目录,如F:/dev/instantclient_11_1
- libdir=${exec_prefix}
- includedir=${prefix}/sdk/include/
- Name: OCI
- Description: Oracle database engine
- Version: 11.2
- Libs: -L${libdir} -loci
- Libs.private:
- Cflags: -I${includedir}
四、设置环境变量
环境变量path下添加instantclient_11_1和 mingw\bin的路径添加PKG_CONFIG_PATH=C:\mingw\lib\pkg-config
添加TNS_ADMIN= F:\dev\instantclient_11_1 \ network\admin\
五、测试
在此执行go getgithub.com/wendal/go-oci8,如果没错那说明大功告成。具体测试代码见github.com\wendal\go-oci8\example下的oracle.go,注意要把里边import中的mattn改成wendal。一下是我的代码:
- package main
- import (
- "database/sql"
- _ "github.com/wendal/go-oci8"
- "log"
- )
- func query() {
- // 为log添加短文件名,方便查看行数
- log.SetFlags(log.Lshortfile | log.LstdFlags)
- // 用户名/密码@实例名 跟sqlplus的conn命令类似
- db,err := sql.Open("oci8","username/pwd@ORCL")
- if err != nil {
- log.Fatal(err)
- }
- defer db.Close()
- rows,err := db.Query("select name from FUB_B")
- if err != nil {
- log.Fatal(err)
- }
- for rows.Next() {
- var name string
- rows.Scan(&name)
- log.Printf("Name = %s,len=%d",name,len(name))
- }
- rows.Close()
- }
- func update() {
- // 为log添加短文件名,"username/pwd@ORCL")
- if err != nil {
- log.Fatal(err)
- }
- defer db.Close()
- stmt,_ := db.Prepare(`UPDATE FUB_B set name ='cnm'`)
- result,err := stmt.Exec()
- if err != nil {
- log.Fatal(err)
- }
- count,_ := result.RowsAffected()
- log.Printf("result count:%d",count)
- }
- func main() {
- update()
- }