Gox语言中操作常见关系型数据库(Oracle、MySQL、SQL Server、SQLite等)-GX28.1

Gox语言操作数据库也非常方便,语言中已经内置了SQLite、MySQL、Oracle、MS SQL Server等数据库的支持。

以Oracle数据库为例来说,当然系统先要安装Oracle驱动,直接去Oracle官方下载对应的驱动安装即可。Windows下建议安装64位Basic Light版就可以,安装过程也很简单,直接解压到某个目录下,然后将该目录(名为类似“D:\tools\instantclient_19_6”的目录)加入到Windows的PATH中,重启命令提示符窗口或者计算机后就可以使用了。或者Gox直接在装有Oracle驱动的目录下运行(例如D:\tools\instantclient_19_6中)也可以。

注意:Windows下Oracle驱动的运行,还需要系统中装有Visual C++的运行时,例如Oracle 19需要Microsoft Visual C++ 2015-2019 Redistributable (X64),去这里下载就行。

访问Oracle数据库进行SQL查询的例子如下:

// sqltk库提供访问数据库的一些简单方法

// 连接数据库,Oralce数据库要使用godror驱动
// 用户名、密码、数据库服务器地址和端口、数据库名等均需要替换成自己的
dbT, errT = sqltk.ConnectDB("godror", `username/password@db.example.com:1521/dbname`)

if errT != nil {
    printfln("数据库连接错误: %v", errT)
    exit()
}

// 注意一定要关闭数据库连接,释放资源,即使是异常退出
defer dbT.Close()

// 拼装SQL语句,建议一般都用拼装的方式,避免传参数的SQL调用方式
// 注意将数据库名、表名和字段名换成自己的
sqlT = `select * from dbname.MY_TABLE_NAME where RECIPE_NO='0200006619210053289'`

// QueryDBNSS函数将查询结果返回为一个二维数组,第一行为列名,第二行开始是数据,所有数据都被转换为字符串表示形式

sqlResultT, errT = sqltk.QueryDBNSS(dbT, sqlT)

if errT != nil {
    printfln("获取数据记录失败:%v", errT)

    exit()
}

// 查看结果
plv(sqlResultT)



例子中使用到了sqltk库,该库的参考文档可以参考这里.

如果一定需要传参数的方式,需要这样做:

...

sqlT = `select * from dbname.MY_TABLE_NAME where RECIE_NO=:v1 and USER_NO=:v2`

sqlResultT, errT = sqltk.QueryDBNSS(dbT, sqlT, '123456', '789065')

...

即QueryDBNSS函数支持后面跟接任意多个参数,而对Oracle来说,可以用“:v1”这样的方式在SQL语句中表示传入参数的占位。注意,参数占位的方法在不同数据库系统中不尽相同,例如MySQL中是直接用问号“?”表示的。

至于SELECT COUNT(*)这样的操作,可以照下面的方法进行:

...

sqlStrT := `SELECT COUNT(*) FROM ANLA_SEND_REG WHERE ERID='` + emplListT[1] + `' AND (NOTE='' OR NOTE IS NULL)`

countT, errT := sqltk.QueryDBCount(dbT, sqlStrT)

...

sqltk.QueryDBCount函数用于进行只返回一个整数的SQL查询语句。

如果要执行UPDATE、DELETE等操作,则要使用sqltk.ExecV函数,

...

sqlStrT := tk.Spr("UPDATE ANLA_SEND_REG SET NOTE='%v', UPDATE_TIME=sysdate WHERE PICI='%v' AND ERID='%v' AND ID='%v'", "YES", batchNoT, emplListT[1], deviceListT[0])

_, affectedCountT, errT := sqltk.ExecV(dbT, sqlStrT)

if errT != nil || affectedCountT != 1 {
  return tk.Spr("更新资产信息失败:%v, %v", errT, sqlStrT)
}

...

这样,基本的数据库操作就都可以实现了。

另外,由于sqltk.ConnectDB函数返回的是Go语言标准库中database/sql中的DB对象,因此可以据此进行符合Go语言标准方式的SQL操作,可以更加细致,实现更加复杂的功能。database/sql的文档可以参看这里

例如,下面的代码在获得了DB对象后进行了一个数据库事务的处理。

...

    txT, errT = dbA.Begin()
    if errT != nil {
        pl("新建事务时发生错误(%v):%v", tk.Spr("argA: %v", argA), errT)
        exit()
    }

    stmtT, errT = txT.Prepare("insert into MY_TABLE (AccNo, Drcrf, Remark, TradeTime) values(:AccNo, :Drcrf,  :Remark, :TradeTime)")
    if errT != nil {
        pl("准备SQL语句更新记录时发生错误(%v):%v", tk.Spr("argA: %v", argA), errT)
        exit()
    }

    _, errT = stmtT.Exec(AccNoG, argA.Drcrf, "remark here", argA.TradeTime)
    if errT != nil {
        stmtT.Close()

        pl("执行SQL插入记录语句时发生错误(%v):%v", tk.Spr("argA: %v", argA), errT)
        exit()
    }

    txT.Commit()

    stmtT.Close()

...


可见Gox语言对于数据库编程的支持还是不错的,注重的是简捷方便。

对于SQLite数据库,数据库驱动名字要把上例中的godror改成sqlite3;MySQL则换成mysql,MS SQL Server则换成sqlserver。

下面再看一个使用SQLite3数据库的例子,SQLite数据库基于文件,无需安装驱动,使用上非常方便,下面这个例子演示了创建一个新的SQLite3的数据库文件,并在其中创建新的表,然后随机插入一些记录,最后进行查询。其中除了数据库创建使用了sqltk库,后续的操作都是使用Go语言标准库的操作,可以借鉴一下。


// 如果存在该库(SQLite库是放在单一的文件中的)则删除该文件
if tk.IfFileExists(`e:\tmpx\test.db`) {
    os.Remove(`e:\tmpx\test.db`)
}

// 创建新库
dbT, errT = sqltk.ConnectDB("sqlite3", `e:\tmpx\test.db`)

if errT != nil {
    printfln("创建数据库时发生错误:%v", errT)
    return
}

// 确保关闭数据库
defer dbT.Close()

//创建表
sqlStmtT = `
create table TEST (ID integer not null primary key, CODE text);
`
_, errT = dbT.Exec(sqlStmtT)
if errT != nil {
    printfln("创建表时发生错误:%v", errT.Error())
    return
}

// 开始一个数据库事务
txT, errT = dbT.Begin()
if errT != nil {
    printfln("新建事务时发生错误:%v", errT.Error())
    return
}

// 准备一个SQL语句,用于向表中插入记录
stmtT, errT = txT.Prepare("insert into TEST(ID, CODE) values(?, ?)")
if errT != nil {
    printfln("准备SQL语句插入记录时发生错误:%v", errT.Error())
    return
}

// 确保关闭SQL语句对象
defer stmtT.Close()

// 向表中插入10条记录
// 每条记录的ID字段用循环变量的值赋值
// CODE字段用随机产生的字符串
for i = 0; i < 10; i++ {
    _, errT = stmtT.Exec(i, tk.GenerateRandomString(5, 8, true, true, true, false, false, false))
    if errT != nil {
        printfln("执行SQL插入记录语句时发生错误:%v", errT.Error())
        return
    }
}

// 执行事务,此时新纪录才会被真正插入到表中
txT.Commit()

// 进行SQL查询
rowsT, errT = dbT.Query("select ID, CODE from TEST")
if errT != nil {
    printfln("执行SQL查询语句时发生错误:%v", errT.Error())
    return
}

// 确保关闭数据库查询结果集对象
defer rowsT.Close()

// 遍历查询结果
for {

    if rowsT.Next() == false {
        break
    }

    idT = ""
    codeT = ""

    // 注意Gox语言中取指针要用符号^
    errT = rowsT.Scan(^idT, ^codeT)
    if errT != nil {
        printfln("遍历查询结果时发生错误:%v", errT.Error())
        return
    }

    printfln("ID: %v, CODE: %v", idT, codeT)
}

// 检查查询结果的错误
errT = rowsT.Err()
if errT != nil {
    printfln("查询结果有错误:%v", errT.Error())
}


代码中已经有详尽的解释,这段代码执行后,将在E盘的tmpx目录下新增test.db文件,这就是代码创建的新SQLite3的数据库。代码执行的输出如下:

E:\scripts>gox sqlite.gox
ID: 0, CODE: MvDo4GMR
ID: 1, CODE: IGMJi
ID: 2, CODE: 7QJe5eY
ID: 3, CODE: Ot13Fq
ID: 4, CODE: LSntYqa
ID: 5, CODE: ZXvb67Lt
ID: 6, CODE: QMueBp5
ID: 7, CODE: OFDcmo1
ID: 8, CODE: fpMTy5
ID: 9, CODE: ZKvlEF

可以看出,数据库记录成功地添加进去了,并且查询也成功了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容