Golang中国

在网上没搜到插入多字段的示例,就照库的例子用:1和:2做占位符,查询正常,插入常量ok(如下),用变量插入就报错了,请知道的高手帮忙回答一下,谢谢了。(oci8有像mysql库的prepare函数没)

_, err = db.Exec("insert into AUTH_SUCESS_201706_FZ values('a','b','c','d',1,2,3,'e',4,5,6,'f',7,8,'g','h','i')")

SQL>  select count(*) from AUTH_SUCESS_201706_FZ;

  COUNT(*)
----------
     1

报错信息:

2017-06-17 04:57:11 <LL_ERROR> ORA-01722: invalid number

使用oerr ora 1722 看解释没看懂说的哪个number无效,是占位符吗?

[root@bogon ~]# oerr ora 1722
01722, 00000, "invalid number"
// *Cause: The specified number was invalid.
// *Action: Specify a valid number.

插入用的代码(下面2种插入方式都报错17222):

_, err = db.Exec("insert into AUTH_SUCESS_201706_FZ values(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17)", lineList[0],lineList[1],lineList[2],lineList[3],lineList[4],lineList[5],lineList[6],lineList[7],lineList[8],lineList[9],lineList[10],lineList[11],lineList[12],lineList[13],lineList[14],lineList[15],lineList[16])

_, err = db.Exec("insert into AUTH_SUCESS_201706_FZ values(:1,:1,:1,:1,:1,:1,:1,:1,:1,:1,:1,:1,:1,:1,:1,:1,:1)", lineList[0],lineList[1],lineList[2],lineList[3],lineList[4],lineList[5],lineList[6],lineList[7],lineList[8],lineList[9],lineList[10],lineList[11],lineList[12],lineList[13],lineList[14],lineList[15],lineList[16])

使用fmt.Println打印lineList[]内容如下,插入的表是按照字段个数和类型建的:

22675029@879150 A4-5D-36-18-59-45 20170106112643 20170106122730 3647 8192 1 192.168.1.1 100 200 1 202.101.99.163 1905 FZ-JA-1020000000002028f20b826979 591 atm 3/1/1:2454.1900 0/0/0/0/0/0 liantong

SQL> desc AUTH_SUCESS_201706_FZ; 表结构:

 Name                                             Null?    Type
 ----------------------------------------------------------------------------------- -------- --------------------------------------------------------
 LOGIN                                                  VARCHAR2(128)
 ANI                                                  VARCHAR2(26)
 START_TIME                                              VARCHAR2(20)
 END_TIME                                              VARCHAR2(20)
 DURATION                                              NUMBER(8)
 KB_IN                                                  NUMBER(8)
 KB_OUT                                               NUMBER(8)
 IPADDR                                               VARCHAR2(16)
 PACKETS_IN                                              NUMBER(8)
 PACKETS_OUT                                              NUMBER(8)
 TERM_CAUSE                                              NUMBER(4)
 TERMSERV_ID                                              VARCHAR2(16)
 TERMSERV_PORT                                              NUMBER(8)
 TRANS_ID                                              NUMBER(8)
 AREA_ID                                              VARCHAR2(4)
 NAS_PORT_ID                                              VARCHAR2(256)
 V_OPERATOR                                              VARCHAR2(256)
5 回复
eric160
#1 eric160 • 2017-06-19 11:01

lineList[]这个切片定义的是什么类型的?看起来应该是string类型的,那你在插入的时候要进行类型转换:
比如DURATION数据库中定义的是数值型,那你就要把lineList[4]转换成int型再插入。
dur,_:=strconv.Atoi(linList[4]),然后再插入dur。
要是觉得上面每一个分开写麻烦也可以这样写:

_, err = db.Exec("insert into AUTH_SUCESS_201706_FZ values(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17)", ...,func()int{dur,_:=strconv.Atoi( lineList[4]);return dur}(),...)

把所有需要转换的值都进行转换了,你可以试一试啊,至于占位符我觉得这个写法应该对,虽然我没用过oracle。

eric160
#2 eric160 • 2017-06-19 11:14

而且你为什么要把插入的数据建成slice?应该建成struct才行,struct字段及类型对应数据库中表的字段及类型,这样使用起来才方便。不用进行数据类型转换。

jimyokl
#3 jimyokl • 2017-06-19 12:55

谢谢eric160,转换后成功插入,谢谢
把插入的数据建成slice是因为这个lines切片存储的是读一个文件后的全部内容(按行存在每个切片元素里面,每行用|分隔的)
现在看来可以正常运行,我打算先这样了,谢谢您的建议。
再问下oci8库有db.Prepare()函数能准备语句吗?

eric160
#4 eric160 • 2017-06-19 13:28

可以的,这是它的API文档,你研究一下:
https://godoc.org/github.com/mattn/go-oci8#OCI8Conn.Prepare
这个是它单元测试,其只有prepare测试,也有多字段插入的写法:
https://github.com/mattn/go-oci8/blob/master/more_test.go

jimyokl
#5 jimyokl • 2017-06-19 14:39

再次感谢eric160帮忙

需要 登录 后方可回复, 如果你还没有账号你可以 注册 一个帐号。