Pure Go Oracle database driver for database/sql.
go get github.com/sijms/go-ora/v2
Requires Oracle server 10.2+. See v3 for the latest version with Oracle 23ai support.
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/sijms/go-ora/v2"
)
func main() {
connStr := "oracle://user:pass@server:1521/service"
db, err := sql.Open("oracle", connStr)
if err != nil {
log.Fatal(err)
}
defer db.Close()
if err := db.Ping(); err != nil {
log.Fatal(err)
}
var version string
err = db.QueryRow("SELECT * FROM v$version").Scan(&version)
if err != nil {
log.Fatal(err)
}
fmt.Println(version)
}
Build connection strings with go_ora.BuildUrl or go_ora.BuildJDBC:
// Basic
connStr := go_ora.BuildUrl("server", 1521, "service", "user", "pass", nil)
// With options
connStr := go_ora.BuildUrl("server", 1521, "service", "user", "pass", map[string]string{
"SSL": "true",
"SSL VERIFY": "false",
"WALLET": "/path/to/wallet",
"TIMEOUT": "60",
"TRACE FILE": "trace.log",
})
// JDBC string
connStr := go_ora.BuildJDBC("user", "pass", "JDBC_STRING", nil)
| Option | Description | Default |
|---|---|---|
TIMEOUT | Socket read/write timeout (seconds, 0 = disabled) | 15 |
CONNECTION TIMEOUT | Connection timeout (seconds, 0 = disabled) | 60 |
FAILOVER | Reconnect attempts on connection loss | 0 |
SSL | Enable TLS/SSL | false |
SSL VERIFY | Verify server certificate | true |
WALLET | Path to Oracle wallet directory | |
AUTH TYPE | OS, KERBEROS, or TCPS | |
DBA PRIVILEGE | SYSDBA or SYSOPER | NONE |
LOB FETCH | pre/inline (default) or post/stream | pre |
client charset | Override client-side character set | |
language / territory | Server message language | |
TRACE FILE | Enable packet logging | |
proxy client name | Proxy user schema |
rows, err := db.Query("SELECT id, name, created_at FROM users")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var (
id int64
name string
createdAt sql.NullTime
)
if err := rows.Scan(&id, &name, &createdAt); err != nil {
log.Fatal(err)
}
fmt.Println(id, name, createdAt)
}
_, err := db.Exec(`CREATE TABLE users (
id NUMBER(10),
name VARCHAR2(50),
created_at DATE
)`)
_, err := db.Exec("BEGIN DBMS_LOCK.sleep(5); END;")
// Input
_, err := db.Exec("INSERT INTO users (id, name) VALUES (:1, :2)", 1, "Alice")
// Named parameters
_, err := db.Exec("INSERT INTO users (id, name) VALUES (:id, :name)", sql.Named("id", 1), sql.Named("name", "Alice"))
// Output
var name string
_, err = db.Exec("BEGIN SELECT name INTO :1 FROM users WHERE id=:2; END;",
go_ora.Out{Dest: &name, Size: 100}, 1)
// Insert
clob := go_ora.Clob{String: "large text value"}
blob := go_ora.Blob{Data: []byte("binary data")}
_, err := db.Exec("INSERT INTO docs (text_col, blob_col) VALUES (:1, :2)", clob, blob)
// Output
var text go_ora.NClob
_, err = db.Exec("BEGIN SELECT text_col INTO :1 FROM docs WHERE id=:2; END;",
go_ora.Out{Dest: &text, Size: 100000}, 1)
type User struct {
Id int64 `db:"ID,number"`
Name string `db:"type=varchar,name=NAME"`
}
// Input
_, err := db.Exec("INSERT INTO users (id, name) VALUES (:ID, :NAME)", User{Id: 1, Name: "Alice"})
// Output (requires direction + size)
_, err = db.Exec("BEGIN SELECT id, name INTO :ID, :NAME FROM users WHERE id=:1; END;",
go_ora.Out{Dest: &User{Id: 1}, Size: 100}, 1)
CREATE OR REPLACE TYPE address_type AS OBJECT (
street VARCHAR2(100),
city VARCHAR2(50)
);
type Address struct {
Street string `udt:"STREET"`
City string `udt:"CITY"`
}
// Register before use
if drv, ok := db.Driver().(*go_ora.OracleDriver); ok {
err := drv.Conn.RegisterType("SCHEMA", "ADDRESS_TYPE", Address{})
}
// Use in queries
var addr Address
rows, err := db.Query("SELECT address_type('123 Main', 'NYC') FROM dual")
rows.Scan(&addr)
v, err := go_ora.NewVector([]float32{0.1, 0.2, 0.3})
_, err = db.Exec("INSERT INTO embeddings (id, vec) VALUES (:1, :2)", 1, v)
// Query
var vec go_ora.Vector
rows.Scan(&vec)
data := vec.Data.([]float32) // cast to slice
rows, err := db.Query("BEGIN :1 := my_func(:2); END;",
go_ora.Out{Dest: &cursor}, 1)
connector, err := go_ora.NewConnector(connStr)
db := sql.OpenDB(connector)
config, err := go_ora.ParseConfig(connStr)
config.RegisterDial(func(ctx context.Context, network, address string) (net.Conn, error) {
// custom dialer
})
go_ora.RegisterConnConfig(config)
db, err := sql.Open("oracle", "")
err := go_ora.AddSessionParameter(db, "nls_language", "english")
err = go_ora.DelSessionParameter(db, "nls_language")
go_ora.SetStringConverter(db, charset, nCharset) // implement IStringConverter
| Method | Options |
|---|---|
| Password | Default (user/pass in connection string) |
| OS Auth (Windows) | AUTH TYPE=OS, OS USER, OS PASS, DOMAIN |
| Kerberos5 | AUTH TYPE=KERBEROS + gokrb5 |
| Client Cert | AUTH TYPE=TCPS + SSL=TRUE + WALLET |
| Wallet | wallet=/path/to/cwallet.sso |
| Proxy | proxy client name=schema_owner |
Data encryption (AES) and integrity checking (SHA) are negotiated via Diffie-Hellman key exchange. Configure on the server side in sqlnet.ora:
SQLNET.ENCRYPTION_SERVER = required
SQLNET.ENCRYPTION_TYPES_SERVER = AES256
SQLNET.CRYPTO_CHECKSUM_SERVER = required
SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER = SHA512
Control client-side behavior:
urlOptions := map[string]string{
"encryption": "required", // accepted/rejected/required
"data integrity": "required",
}
database/sql compatible -- works with standard Go DB poolsdbms_output.NewOutput(conn, bufferSize)RegisterDial for custom connection dialersParseConfig / RegisterConnConfig APIgo_ora.Object wrapper for UDT parametersDelSessionParamtime.Time{} as input for DATE/TIMESTAMPNewDriver / NewConnectorSetStringConverter for unsupported charsetsWrapRefCursor converts RefCursor to *sql.Rowsdatabase/sql failover via driver.ErrBadConn*sql.Rowssql.Named)pre/post)BuildUrl for special charactersSee examples/ for complete code samples covering CRUD, LOB, UDT, arrays, BulkCopy, RefCursor, and more.
Go
100.0%
Pure Go Oracle database driver for database/sql.
go get github.com/sijms/go-ora/v2
Requires Oracle server 10.2+. See v3 for the latest version with Oracle 23ai support.
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/sijms/go-ora/v2"
)
func main() {
connStr := "oracle://user:pass@server:1521/service"
db, err := sql.Open("oracle", connStr)
if err != nil {
log.Fatal(err)
}
defer db.Close()
if err := db.Ping(); err != nil {
log.Fatal(err)
}
var version string
err = db.QueryRow("SELECT * FROM v$version").Scan(&version)
if err != nil {
log.Fatal(err)
}
fmt.Println(version)
}
Build connection strings with go_ora.BuildUrl or go_ora.BuildJDBC:
// Basic
connStr := go_ora.BuildUrl("server", 1521, "service", "user", "pass", nil)
// With options
connStr := go_ora.BuildUrl("server", 1521, "service", "user", "pass", map[string]string{
"SSL": "true",
"SSL VERIFY": "false",
"WALLET": "/path/to/wallet",
"TIMEOUT": "60",
"TRACE FILE": "trace.log",
})
// JDBC string
connStr := go_ora.BuildJDBC("user", "pass", "JDBC_STRING", nil)
| Option | Description | Default |
|---|---|---|
TIMEOUT | Socket read/write timeout (seconds, 0 = disabled) | 15 |
CONNECTION TIMEOUT | Connection timeout (seconds, 0 = disabled) | 60 |
FAILOVER | Reconnect attempts on connection loss | 0 |
SSL | Enable TLS/SSL | false |
SSL VERIFY | Verify server certificate | true |
WALLET | Path to Oracle wallet directory | |
AUTH TYPE | OS, KERBEROS, or TCPS | |
DBA PRIVILEGE | SYSDBA or SYSOPER | NONE |
LOB FETCH | pre/inline (default) or post/stream | pre |
client charset | Override client-side character set | |
language / territory | Server message language | |
TRACE FILE | Enable packet logging | |
proxy client name | Proxy user schema |
rows, err := db.Query("SELECT id, name, created_at FROM users")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var (
id int64
name string
createdAt sql.NullTime
)
if err := rows.Scan(&id, &name, &createdAt); err != nil {
log.Fatal(err)
}
fmt.Println(id, name, createdAt)
}
_, err := db.Exec(`CREATE TABLE users (
id NUMBER(10),
name VARCHAR2(50),
created_at DATE
)`)
_, err := db.Exec("BEGIN DBMS_LOCK.sleep(5); END;")
// Input
_, err := db.Exec("INSERT INTO users (id, name) VALUES (:1, :2)", 1, "Alice")
// Named parameters
_, err := db.Exec("INSERT INTO users (id, name) VALUES (:id, :name)", sql.Named("id", 1), sql.Named("name", "Alice"))
// Output
var name string
_, err = db.Exec("BEGIN SELECT name INTO :1 FROM users WHERE id=:2; END;",
go_ora.Out{Dest: &name, Size: 100}, 1)
// Insert
clob := go_ora.Clob{String: "large text value"}
blob := go_ora.Blob{Data: []byte("binary data")}
_, err := db.Exec("INSERT INTO docs (text_col, blob_col) VALUES (:1, :2)", clob, blob)
// Output
var text go_ora.NClob
_, err = db.Exec("BEGIN SELECT text_col INTO :1 FROM docs WHERE id=:2; END;",
go_ora.Out{Dest: &text, Size: 100000}, 1)
type User struct {
Id int64 `db:"ID,number"`
Name string `db:"type=varchar,name=NAME"`
}
// Input
_, err := db.Exec("INSERT INTO users (id, name) VALUES (:ID, :NAME)", User{Id: 1, Name: "Alice"})
// Output (requires direction + size)
_, err = db.Exec("BEGIN SELECT id, name INTO :ID, :NAME FROM users WHERE id=:1; END;",
go_ora.Out{Dest: &User{Id: 1}, Size: 100}, 1)
CREATE OR REPLACE TYPE address_type AS OBJECT (
street VARCHAR2(100),
city VARCHAR2(50)
);
type Address struct {
Street string `udt:"STREET"`
City string `udt:"CITY"`
}
// Register before use
if drv, ok := db.Driver().(*go_ora.OracleDriver); ok {
err := drv.Conn.RegisterType("SCHEMA", "ADDRESS_TYPE", Address{})
}
// Use in queries
var addr Address
rows, err := db.Query("SELECT address_type('123 Main', 'NYC') FROM dual")
rows.Scan(&addr)
v, err := go_ora.NewVector([]float32{0.1, 0.2, 0.3})
_, err = db.Exec("INSERT INTO embeddings (id, vec) VALUES (:1, :2)", 1, v)
// Query
var vec go_ora.Vector
rows.Scan(&vec)
data := vec.Data.([]float32) // cast to slice
rows, err := db.Query("BEGIN :1 := my_func(:2); END;",
go_ora.Out{Dest: &cursor}, 1)
connector, err := go_ora.NewConnector(connStr)
db := sql.OpenDB(connector)
config, err := go_ora.ParseConfig(connStr)
config.RegisterDial(func(ctx context.Context, network, address string) (net.Conn, error) {
// custom dialer
})
go_ora.RegisterConnConfig(config)
db, err := sql.Open("oracle", "")
err := go_ora.AddSessionParameter(db, "nls_language", "english")
err = go_ora.DelSessionParameter(db, "nls_language")
go_ora.SetStringConverter(db, charset, nCharset) // implement IStringConverter
| Method | Options |
|---|---|
| Password | Default (user/pass in connection string) |
| OS Auth (Windows) | AUTH TYPE=OS, OS USER, OS PASS, DOMAIN |
| Kerberos5 | AUTH TYPE=KERBEROS + gokrb5 |
| Client Cert | AUTH TYPE=TCPS + SSL=TRUE + WALLET |
| Wallet | wallet=/path/to/cwallet.sso |
| Proxy | proxy client name=schema_owner |
Data encryption (AES) and integrity checking (SHA) are negotiated via Diffie-Hellman key exchange. Configure on the server side in sqlnet.ora:
SQLNET.ENCRYPTION_SERVER = required
SQLNET.ENCRYPTION_TYPES_SERVER = AES256
SQLNET.CRYPTO_CHECKSUM_SERVER = required
SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER = SHA512
Control client-side behavior:
urlOptions := map[string]string{
"encryption": "required", // accepted/rejected/required
"data integrity": "required",
}
database/sql compatible -- works with standard Go DB poolsdbms_output.NewOutput(conn, bufferSize)RegisterDial for custom connection dialersParseConfig / RegisterConnConfig APIgo_ora.Object wrapper for UDT parametersDelSessionParamtime.Time{} as input for DATE/TIMESTAMPNewDriver / NewConnectorSetStringConverter for unsupported charsetsWrapRefCursor converts RefCursor to *sql.Rowsdatabase/sql failover via driver.ErrBadConn*sql.Rowssql.Named)pre/post)BuildUrl for special charactersSee examples/ for complete code samples covering CRUD, LOB, UDT, arrays, BulkCopy, RefCursor, and more.
Go
100.0%