Files
oracle/README.md
T

7.0 KiB
Raw Blame History

GORM Oracle Driver

基于 go-ora 实现的 GORM Oracle 数据库驱动,内置版本感知能力、驱动抽象层go-ora / godror 可切换)、自定义回调体系(INSERT/UPDATE/DELETE/QUERY)与完整测试套件。

特性

  • 版本感知:自动识别 Oracle 数据库版本,按版本适配 SQL 语法与类型
    • 12c+:原生 IDENTITY 列、OFFSET / FETCH 分页、DEFAULT <seq>.NEXTVAL
    • 11g:自动创建序列 + BEFORE INSERT 触发器模拟自增,分页改写为 ROWNUM
    • 21c+:原生 BOOLEAN 列类型(更早版本用 NUMBER(1) 模拟)
    • 23ai:支持 VECTOR 类型(AI Vector Search
    • 12c+Extended):VARCHAR2 支持最大 32k 字节,超出自动降级为 CLOB
  • 驱动抽象层driver_adapter):统一 go-ora(纯 Go)与 godror(基于 ODPI-C)的差异,通过 Config.DriverType 一键切换
  • 自定义回调体系
    • INSERT ... RETURNING INTO:支持默认值/自增字段回填,批量插入逐行执行保证一致性与返回值正确性
    • ON CONFLICTMERGE INTO:自动改写为 Oracle MERGE 语法
    • 单行 UPDATE/DELETE ... RETURNING INTO
    • WHERE 安全检查:无有效 WHERE 条件时拒绝执行 UPDATE/DELETE,避免全表误操作(软删除条件除外)
    • 软删除支持
  • 数据迁移Migrator):
    • 表/列/索引/约束的增删改查,列名大小写自动映射(Oracle 返回大写列名)
    • 从数据字典(USER_TAB_COLUMNS)获取真实数据类型,避免 AutoMigrate 误判触发多余 ALTER
    • Oracle 不支持原生 ON UPDATE 外键操作,自动生成触发器模拟 CASCADE / SET NULL
    • Oracle 保留字自动加引号
  • 命名策略统一转换为大写

环境要求

  • Oracle 11g、12c 及以上(支持 21c、23ai 等新版本)
  • Golang 1.22+
  • GORM v1.31.2+
  • 底层驱动默认使用 go-ora v2(纯 Go 实现,无需安装 ODPI-C

安装

go get git.charlienet.top/go/oracle

快速开始

import (
    "gorm.io/gorm"

    oracle "git.charlienet.top/go/oracle"
)

func main() {
    dsn := "oracle://user:password@127.0.0.1:1521/XE?SSL=false"
    db, err := gorm.Open(oracle.Open(dsn), &gorm.Config{})
    if err != nil {
        panic(err)
    }
    // do something...
}

DSN 格式

DSN 使用 go-ora 的 URL 格式:

oracle://user:password@host:port/service?SSL=false&CONNECTION TIMEOUT=90&SOCKET TIMEOUT=90

常用参数:

  • SSL:是否启用 TLS 加密
  • CONNECTION TIMEOUT:连接建立超时(秒),go-ora v2.9.0 起该参数只控制连接建立
  • SOCKET TIMEOUT:socket 读写超时(秒),需要读超时保护时配合 CONNECTION TIMEOUT 一起设置
  • LANGUAGE / TERRITORY:会话语言与地区,如 LANGUAGE=SIMPLIFIED+CHINESE&TERRITORY=CHINA

配置项

使用 oracle.New(Config{}) 可获得更多配置能力:

import (
    "gorm.io/gorm"

    oracle "git.charlienet.top/go/oracle"
    "git.charlienet.top/go/oracle/driver_adapter"
)

db, err := gorm.Open(oracle.New(oracle.Config{
    DSN:                  "oracle://user:password@127.0.0.1:1521/XE",
    DriverType:           driver_adapter.DriverGoOra, // 驱动类型:go-ora(默认)或 godror
    SkipQuoteIdentifiers: false,                      // 是否跳过标识符引用
    DBName:               "SCOTT",                    // 指定 Schema(表名将带 Schema 前缀)
    // Conn: 传入已存在的 *sql.DB 连接池
}), &gorm.Config{})
配置项 说明
DSN 连接串
DriverType 底层驱动类型:driver_adapter.DriverGoOra(默认)/ driver_adapter.DriverGodror
SkipQuoteIdentifiers true 时不引用标识符
DBName 指定 Schema 名,开启后表名自动带上 SCHEMA.TABLE 前缀
Conn 直接传入已建立的连接池(*sql.DB),此时忽略 DSN
DefaultStringSize 字符串字段未指定大小时的默认长度(默认 1024)

驱动抽象层

driver_adapter 包统一了不同 Oracle 驱动的差异(输出参数、LOB、批量数据、多行 RETURNING 等能力探测),默认使用 go-ora(纯 Go,无需本地依赖)。如需切换到 godror:

  1. 在代码中显式指定 DriverType: driver_adapter.DriverGodror
  2. 引入 godror 依赖并使用 -tags godror 构建(driver_adapter/godror.gogo:build godror 约束)

版本适配行为

特性 Oracle 11g Oracle 12c+ Oracle 21c+ Oracle 23ai
自增主键 序列 + BEFORE INSERT 触发器 GENERATED BY DEFAULT AS IDENTITY 同 12c 同 12c
DEFAULT <seq>.NEXTVAL 建表后创建触发器实现 原生 DEFAULT 子句 同 12c 同 12c
分页(Limit/Offset ROWNUM 改写 OFFSET n ROWS FETCH NEXT n ROWS ONLY 同 12c 同 12c
BOOLEAN NUMBER(1) NUMBER(1) 原生 BOOLEAN 原生 BOOLEAN
超长字符串(>4000 CLOB VARCHAR2(n)32k 同 12c 同 12c
VECTOR 类型 不支持 不支持 不支持 支持

版本通过连接后执行 select version from product_component_version where rownum = 1 自动探测,无需手动配置。

常用操作示例

// 创建(自动回填自增主键/默认值字段)
user := User{Name: "Alice", Email: "alice@example.com"}
db.Create(&user) // user.ID 自动回填

// 批量插入
users := []User{{Name: "A"}, {Name: "B"}}
db.Create(&users)

// Upsert(自动改写为 MERGE INTO
db.Clauses(clause.OnConflict{DoUpdates: clause.AssignmentColumns([]string{"name"})}).
    Create(&user)

// 更新(无 WHERE 条件会被拒绝)
db.Model(&User{}).Where("id = ?", 1).Update("name", "Bob")

// 删除(无 WHERE 条件会被拒绝;带 DeletedAt 字段时自动软删除)
db.Delete(&User{}, 1)
db.Unscoped().Delete(&User{}, 1) // 强制物理删除

注意事项与已知限制

  • UPDATE / DELETE 执行了 WHERE 安全检查:缺少有效条件(包括仅有软删除条件)时返回 missing WHERE condition 错误
  • Oracle 仅支持单行 RETURNING:多行 UPDATE 不启用 RETURNING 回填;go-ora 不支持批量 INSERT + RETURNING,驱动采用逐行插入保证返回值正确
  • 创建表时若关联关系声明了 ON UPDATE CASCADE / SET NULL,驱动会自动生成同名触发器;删除表时需先删除依赖的表或使用 CASCADE CONSTRAINTS(已内置)
  • 11g 下通过序列 + 触发器模拟自增时,触发器和序列按 SEQ_<table> / TRG_<table> 命名,删除表会级联清理
  • 布尔值在写入时转换为 1/0,读取时转换回 Go bool

测试

tests/ 目录下为集成测试套件(创建、查询、更新、删除、软删除、Hook、迁移、序列、MERGE 等),需要真实的 Oracle 数据库:

ORACLE_DSN="oracle://user:password@host:1521/service" go test ./tests/...

驱动单元测试(无需数据库):

go test ./...

License

License