获取最后插入的ID(Go + Oracle)

3
我需要使用go-oci8驱动程序(https://github.com/mattn/go-oci8)和sqlx(https://github.com/jmoiron/sqlx)从我的go应用程序向Oracle数据库中插入两个记录。第二个记录引用了前一个记录的外键。因此,在插入第二个记录之前,我需要拥有第一个记录的主键(它是通过在第一个表上使用插入前触发器从序列中分配的)。
所以我尝试进行了实验以获取最后插入的id:
create table t(x int primary key);
create sequence x_seq;

LastInsertId对我来说失败了:

import(
    "fmt"
    "github.com/jmoiron/sqlx"
    _ "github.com/mattn/go-oci8"
)

func main(){
    db, err := sqlx.Connect("oci8", "integr/integr@localhost:49161/xe")
    if err != nil {
       fmt.Println(err)
    }
    sql := "insert into t values(x_seq.nextval)"
    r, err := db.Exec(sql)
    if err != nil {
       fmt.Println(err)
    }
    fmt.Println(r.RowsAffected())
    fmt.Println(r.LastInsertId())
}

输出:

1 <nil>
0 LastInsertId not supported

然后我尝试创建一个存储函数,用于插入记录并返回主键。
create function f(x int) return int as
v int;
begin
    insert into t values(x)
    returning x into v;
    return v;
end;

但是我没能找到获取其结果的方法。PostgreSQL风格的选择语句失败了:
SQL> select f(9) from dual;
select f(9) from dual
       *
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "INTEGR.F", line 1

OCI8风格的变量绑定不起作用:
package main

import(
    "fmt"
    "github.com/jmoiron/sqlx"
    _ "github.com/mattn/go-oci8"
)

func main(){
    db, err := sqlx.Connect("oci8", "integr/integr@localhost:49161/xe")
    if err != nil {
       fmt.Println(err)
    }
    sql := sqlx.Rebind(sqlx.NAMED,"begin ? := f(?); end;")
    var a int
    _, err = db.Exec(sql, a, 333)
    if err != nil {
       fmt.Println(err)
    }
    fmt.Println(sql)
    fmt.Println(a)
}

输出:

begin :arg1 := f(:arg2); end;
0

如何在Go中从Oracle获取最后插入的ID或从存储函数获取值?

你可以使用ORM获取最后插入行(最后保存的对象)的ID,或者通过触发器停止插入ID。手动获取seq.nextVal并对其进行操作。 - Krishnat Molawade
也许你可以修复go-oci8驱动程序: https://github.com/mattn/go-oci8/blob/master/oci8.go? - kostya
2个回答

0

嗨,我不了解Go语言,但我知道Oracle返回查询。

我曾经在PHP中遇到同样的问题,但是我使用这个查询解决了它。

insert into table (field1,field2,field3)
values (val1,val2,val3) return primaryfield_id into :xx

它会自动返回值到你的Go变量中(我猜) 请试一下吧


我也尝试过了。在调用后,绑定到:xx的变量仍然为空。看起来golang的“database/sql”包无法将值返回到绑定的变量中,只能将它们传递给查询。 - Sergey Melekhin
你能把你的返回查询v的输出发送给我吗? - Chintan Gor
在Go语言中,输出为"",就像我之前所说的那样。绑定的变量仍然为空。 - Sergey Melekhin

0

返回ID的变量必须作为最后一个参数包含在Exec参数的枚举中:

func (c *AppController) InsertEmployee(employee *Employee) (int64, error) {

  var id int64

  insert := `insert into emp (firstName, lastName)
                    values (:firstName, :lastName) 
                        RETURNING id INTO :id`

  _, err := c.db.Exec(insert, &bundle.firstName, &bundle.lastName, &id)

  if err != nil {
    return id, err
  }

  return id, nil

}

通过函数LastInsertId()获取生成的ID的可能性似乎在Oracle中无法实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接