LoginSignup
3
2

More than 3 years have passed since last update.

Docker上のgolangから Oracle接続やってみました。

Last updated at Posted at 2020-04-22

#はじめに
コロナ禍で自宅勤務になったので、今更ながらDockerやgolangでも使ってみようと思い少しお勉強してみました。
Qiitaで記事書くのも初めてなので優しくしてね(汗)
仕事ではOracleが多いのでgolangからOracleに接続を試みます。

#評価環境
 ホストOS:CentOS Linux release 7.7.1908 (Core)
 Docker:Docker version 19.03.8, build afacb8b
 DB Server:Oracle Database 11g Express Edition Release 11.2.0.2.0

#Oracleクライアント
 インスタントクライアントをOTN(Oracle Technology Network)からダウンロードします。
 今回は入手できた最新の19.6を使いました。
  instantclient-basic-linux.x64-19.6.0.0.0dbru.zip
  instantclient-sdk-linux.x64-19.6.0.0.0dbru.zip
  instantclient-sqlplus-linux.x64-19.6.0.0.0dbru.zip
 sqlplusは必須ではありませんが接続確認用に入れています。

#接続ライブラリ
 mattn/go-oci8 というのがあるらしいのでそれを使っています。

#実行手順
 host# はホストのrootアカウントで実行
 container# はDockerコンテナ上のrootアカウントで実行

イメージを取得して実行(デーモンで起動したいのだがExitedになってしまう)

host# docker pull golang
host# docker run -it --name gogo golang
container# exit

コンテナにモジュールをコピーしてコンテナに接続

host# docker start gogo
host# docker cp instantclient-basic-linux.x64-19.6.0.0.0dbru.zip gogo:/usr/lib
host# docker cp instantclient-sdk-linux.x64-19.6.0.0.0dbru.zip gogo:/usr/lib
host# docker cp instantclient-sqlplus-linux.x64-19.6.0.0.0dbru.zip gogo:/usr/lib
host# docker exec -it gogo /bin/bash

必要なモジュールをインストール後、Oracleクライアント/usr/lib配下に展開

container# apt-get update
container# apt-get install -y vim libaio1 unzip
container# cd /usr/lib
container# unzip instantclient-basic-linux.x64-19.6.0.0.0dbru.zip
container# unzip instantclient-sdk-linux.x64-19.6.0.0.0dbru.zip
container# unzip instantclient-sqlplus-linux.x64-19.6.0.0.0dbru.zip

環境変数を設定(本来なら.bash_profileに書くべきですが省略)

container# export LD_LIBRARY_PATH=/usr/lib/instantclient_19_6:$LD_LIBRARY_PATH
container# export NLS_LANG=JAPANESE_JAPAN.AL32UTF8

sqlplusで接続してみる。日本語で表示されたのでNLS_LANGもちゃんと効いている様子。

container# /usr/lib/instantclient_19_6/sqlplus scott/tiger@dbhost:1521/xe
SQL*Plus: Release 19.0.0.0.0 - Production on 水 4月 22 09:24:41 2020
Version 19.6.0.0.0
Copyright (c) 1982, 2019, Oracle.  All rights reserved.
Oracle Database 11g Release 11.2.0.4.0 - 64bit Production
に接続されました。
SQL>exit
container# 

よく分からないがoci8.pc というファイルが必要らしいので作成

container# vi /usr/lib/pkgconfig/oci8.pc
oci8.pc
prefix=/usr/lib/instantclient_19_6/
libdir=${prefix}
includedir=${prefix}sdk/include/

Name: oci8
Description: Oracle Instant Client
Version: 19.6
Libs: -L${libdir} -lclntsh
Libs.private:
Cflags: -I${includedir}

githubからgo-oci8を取得

container# cd $GOPATH/src
container# go get github.com/mattn/go-oci8

動作確認用のプログラム作成

test.go
package main

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

func execSQL(db *sql.DB, sql string) bool{
	_,err := db.Exec(sql)
	if err != nil {
		fmt.Println(err)
		return false
	} else {
		return true
	}
}

func main() {
	db, err := sql.Open("oci8", os.Args[1])
	if err != nil {
		fmt.Println(err)
		return
	}
	defer db.Close()
	if !execSQL(db,"create table HOGE (NUM number(2),WORD varchar2(10))"){
		return
	}
	if !execSQL(db,"insert into HOGE values (1,'One')"){
		return
	}
	if !execSQL(db,"insert into HOGE values (2,'Two')"){
		return
	}
	if !execSQL(db,"insert into HOGE values (3,'Three')"){
		return
	}

	rows ,err := db.Query("select NUM,WORD  from HOGE order by NUM")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer rows.Close()
	for rows.Next(){
		var num int 
		var word string

		rows.Scan(&num, &word)
		fmt.Println(num, word)
	}
	_,err = db.Exec("drop table HOGE")
}

実行してみる

container# go run test.go scott/tiger@dbhost:1521/xe
1 One
2 Two
3 Three
container#

ということで何とか動きましたとさ。めでたし めでたし

3
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2