golang Oracle数据库SQL操作驱动插件库go-oci8的使用

golang Oracle数据库SQL操作驱动插件库go-oci8的使用

go-oci8简介

Golang Oracle数据库驱动,符合Go database/sql接口规范。

安装步骤

  1. 安装Oracle完整客户端或Instant Client

  2. 安装C/C++编译器

  3. 安装pkg-config,编辑oci8.pc配置文件,然后设置环境变量PKG_CONFIG_PATH指向oci8.pc文件位置 (或者可以使用Go标签noPkgConfig,然后设置环境变量CGO_CFLAGS和CGO_LDFLAGS)

  4. 使用Go 1.9或更高版本安装:

go get github.com/mattn/go-oci8

oci8.pc配置示例

Windows配置示例

prefix=/devel/target/XXXXXXXXXXXXXXXXXXXXXXXXXX
exec_prefix=${prefix}
libdir=C:/app/instantclient_12_2/sdk/oci/lib/msvc
includedir=C:/app/instantclient_12_2/sdk/include

glib_genmarshal=glib-genmarshal
gobject_query=gobject-query
glib_mkenums=glib-mkenums

Name: oci8
Description: oci8 library
Libs: -L${libdir} -loci
Cflags: -I${includedir}
Version: 12.2

Linux配置示例

prefix=/devel/target/XXXXXXXXXXXXXXXXXXXXXXXXXX
exec_prefix=${prefix}
libdir=/usr/lib/oracle/12.2/client64/lib
includedir=/usr/include/oracle/12.2/client64

glib_genmarshal=glib-genmarshal
gobject_query=gobject-query
glib_mkenums=glib-mkenums

Name: oci8
Description: oci8 library
Libs: -L${libdir} -lclntsh
Cflags: -I${includedir}
Version: 12.2

MacOS配置示例

prefixdir=/Users/<username>/Downloads/instantclient_12_2/
libdir=${prefixdir}
includedir=${prefixdir}/sdk/include

Name: OCI
Description: Oracle database driver
Version: 12.2
Libs: -L${libdir} -lclntsh
Cflags: -I${includedir}

MacOS还需要设置环境变量:

export LD_LIBRARY_PATH=/Users/<username>/Downloads/instantclient_12_2
export PKG_CONFIG_PATH=/Users/<username>/Downloads/instantclient_12_2

使用示例

基本查询示例

package main

import (
    "database/sql"
    "fmt"
    "log"
    
    _ "github.com/mattn/go-oci8"
)

func main() {
    // 连接Oracle数据库
    db, err := sql.Open("oci8", "user/password@host:port/service_name")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // 执行查询
    rows, err := db.Query("SELECT * FROM employees WHERE employee_id > :1", 100)
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()
    
    // 处理查询结果
    for rows.Next() {
        var (
            id     int
            name   string
            salary float64
        )
        if err := rows.Scan(&id, &name, &salary); err != nil {
            log.Fatal(err)
        }
        fmt.Printf("ID: %d, Name: %s, Salary: %.2f\n", id, name, salary)
    }
    
    if err := rows.Err(); err != nil {
        log.Fatal(err)
    }
}

插入数据示例

package main

import (
    "database/sql"
    "log"
    
    _ "github.com/mattn/go-oci8"
)

func main() {
    db, err := sql.Open("oci8", "user/password@host:port/service_name")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // 准备插入语句
    stmt, err := db.Prepare("INSERT INTO employees (employee_id, name, salary) VALUES (:1, :2, :3)")
    if err != nil {
        log.Fatal(err)
    }
    defer stmt.Close()
    
    // 执行插入
    res, err := stmt.Exec(101, "John Doe", 50000.00)
    if err != nil {
        log.Fatal(err)
    }
    
    // 获取影响行数
    rowsAffected, err := res.RowsAffected()
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Inserted %d rows", rowsAffected)
}

事务处理示例

package main

import (
    "database/sql"
    "log"
    
    _ "github.com/mattn/go-oci8"
)

func main() {
    db, err := sql.Open("oci8", "user/password@host:port/service_name")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // 开始事务
    tx, err := db.Begin()
    if err != nil {
        log.Fatal(err)
    }
    
    // 执行事务中的操作
    _, err = tx.Exec("UPDATE accounts SET balance = balance - 100 WHERE account_id = 1")
    if err != nil {
        tx.Rollback()
        log.Fatal(err)
    }
    
    _, err = tx.Exec("UPDATE accounts SET balance = balance + 100 WHERE account_id = 2")
    if err != nil {
        tx.Rollback()
        log.Fatal(err)
    }
    
    // 提交事务
    err = tx.Commit()
    if err != nil {
        log.Fatal(err)
    }
    
    log.Println("Transaction completed successfully")
}

作者

Yasuhiro Matsumoto (a.k.a mattn)

特别感谢

Jamil Djadala


更多关于golang Oracle数据库SQL操作驱动插件库go-oci8的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang Oracle数据库SQL操作驱动插件库go-oci8的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


go-oci8: Golang Oracle数据库驱动使用指南

go-oci8 是一个用于连接和操作Oracle数据库的Golang驱动。下面我将详细介绍如何使用这个驱动进行Oracle数据库操作。

安装go-oci8

首先需要安装go-oci8驱动:

go get github.com/mattn/go-oci8

系统依赖

go-oci8需要Oracle客户端库(OCI)的支持。在Linux/Unix上需要安装Oracle Instant Client或完整Oracle客户端,在Windows上也需要配置OCI环境。

基本使用示例

1. 连接Oracle数据库

package main

import (
	"database/sql"
	"fmt"
	"log"
	_ "github.com/mattn/go-oci8"
)

func main() {
	// 连接字符串格式: user/password@host:port/sid
	// 或者使用TNS名称: user/password@tnsname
	db, err := sql.Open("oci8", "scott/tiger@localhost:1521/orcl")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	err = db.Ping()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("成功连接到Oracle数据库")
}

2. 执行查询操作

func queryExample(db *sql.DB) {
	rows, err := db.Query("SELECT empno, ename, sal FROM emp WHERE deptno = :1", 10)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var empno int
		var ename string
		var sal float64
		err = rows.Scan(&empno, &ename, &sal)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("员工号: %d, 姓名: %s, 薪资: %.2f\n", empno, ename, sal)
	}

	if err = rows.Err(); err != nil {
		log.Fatal(err)
	}
}

3. 执行插入操作

func insertExample(db *sql.DB) {
	// 使用命名参数
	result, err := db.Exec(`
		INSERT INTO emp (empno, ename, job, sal, deptno) 
		VALUES (:1, :2, :3, :4, :5)`,
		8001, "张三", "程序员", 8500, 10)
	if err != nil {
		log.Fatal(err)
	}

	rowsAffected, err := result.RowsAffected()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("插入了 %d 行数据\n", rowsAffected)
}

4. 执行事务操作

func transactionExample(db *sql.DB) {
	tx, err := db.Begin()
	if err != nil {
		log.Fatal(err)
	}

	// 执行事务中的多个操作
	_, err = tx.Exec("UPDATE emp SET sal = sal * 1.1 WHERE deptno = :1", 10)
	if err != nil {
		tx.Rollback()
		log.Fatal(err)
	}

	_, err = tx.Exec("INSERT INTO emp_audit (action, emp_count, change_date) VALUES ('SAL_UPDATE', 5, SYSDATE)")
	if err != nil {
		tx.Rollback()
		log.Fatal(err)
	}

	err = tx.Commit()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("事务执行成功")
}

高级特性

1. 处理CLOB/BLOB类型

func clobExample(db *sql.DB) {
	var clobData string
	err := db.QueryRow("SELECT resume FROM employees WHERE empno = :1", 7369).Scan(&clobData)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("CLOB内容:", clobData)
}

func blobExample(db *sql.DB) {
	var blobData []byte
	err := db.QueryRow("SELECT photo FROM employees WHERE empno = :1", 7369).Scan(&blobData)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("BLOB数据长度:", len(blobData))
}

2. 调用存储过程

func callProcedure(db *sql.DB) {
	// 调用无返回值的存储过程
	_, err := db.Exec("BEGIN raise_salary(:1, :2); END;", 7369, 500)
	if err != nil {
		log.Fatal(err)
	}

	// 调用有返回值的存储过程
	var newSalary float64
	err = db.QueryRow(`
		BEGIN 
			get_employee_salary(:1, :2); 
		END;`,
		7369, sql.Out{Dest: &newSalary}).Scan(&newSalary)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("新工资: %.2f\n", newSalary)
}

连接池配置

func connectionPoolExample() {
	db, err := sql.Open("oci8", "scott/tiger@localhost:1521/orcl")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 设置连接池参数
	db.SetMaxOpenConns(10)    // 最大打开连接数
	db.SetMaxIdleConns(5)     // 最大空闲连接数
	db.SetConnMaxLifetime(30 * time.Minute) // 连接最大生命周期

	// 使用连接池...
}

注意事项

  1. OCI环境配置:确保Oracle客户端库正确安装并配置了环境变量(如PATH、LD_LIBRARY_PATH等)

  2. 字符集问题:Oracle数据库通常使用AL32UTF8字符集,确保应用程序字符集与之匹配

  3. 日期时间处理:Oracle的DATE类型会被映射为time.Time类型

  4. NULL值处理:使用sql.NullString、sql.NullInt64等类型处理可能为NULL的列

  5. 性能考虑:对于大量数据操作,考虑使用批量插入或数组绑定等技术

go-oci8提供了完整的Oracle数据库访问能力,包括事务、存储过程调用、大对象处理等特性。通过合理配置连接池和优化SQL语句,可以构建高效的Oracle数据库应用。

回到顶部