database/sql和database/sql/driver中的命名参数

database/sql和database/sql/driver中的命名参数,sql,database,go,neo4j,driver,Sql,Database,Go,Neo4j,Driver,我试图找出在go的内置数据库/sql包中使用命名参数的模式。我查看了oracle驱动程序,但它似乎只是C库的包装。人们是否以优雅的方式解决了这个问题?到目前为止,我刚刚解决了这个问题,将{0},{1}作为单元测试中的参数,但是如果能够正常地将它们用作映射[string]接口{}之类的东西,那就太好了。有没有人有一个看似惯用的想法或实现 作为参考,这里有一个测试: db := testConn() stmt, err := db.Prepare("return {0} as int1, {1} a

我试图找出在go的内置数据库/sql包中使用命名参数的模式。我查看了oracle驱动程序,但它似乎只是C库的包装。人们是否以优雅的方式解决了这个问题?到目前为止,我刚刚解决了这个问题,将
{0}
{1}
作为单元测试中的参数,但是如果能够正常地将它们用作
映射[string]接口{}
之类的东西,那就太好了。有没有人有一个看似惯用的想法或实现

作为参考,这里有一个测试:

db := testConn()
stmt, err := db.Prepare("return {0} as int1, {1} as int2")
if err != nil {
   t.Fatal(err)
}
rows, err := stmt.Query(123, 456)
if err != nil {
   t.Fatal(err)
}
rows.Next()

var test int
var test2 int
err = rows.Scan(&test, &test2)
if err != nil {
   t.Fatal(err)
}
if test != 123 {
   t.Fatal("test != 123;", test)
}
if test2 != 456 {
   t.Fatal("test2 != 456;", test2)
}
我在
Query
中所做的是:

func (stmt *cypherStmt) Query(args []driver.Value) (driver.Rows, error) {
   cyphReq := cypherRequest{
      Query: stmt.query,
   }
   if len(args) > 0 {
      cyphReq.Params = make(map[string]interface{})
   }
   for idx, e := range args {
      cyphReq.Params[strconv.Itoa(idx)] = e
   }
...

我在名为sqlx的数据库/sql之上使用包装器 你可以看看他是怎么做到的

有关如何选择到元组的示例

type Person struct {
    FirstName string `db:"first_name"`
    LastName  string `db:"last_name"`
    Email     string
}
jason = Person{}
err = db.Get(&jason, "SELECT * FROM person WHERE first_name=$1", "Jason")
fmt.Printf("%#v\n", jason)
// Person{FirstName:"Jason", LastName:"Moiron", Email:"jmoiron@jmoiron.net"}
有关如何插入元组的示例

dude := Person{
    FirstName:"Jason", 
    LastName:"Moiron", 
    Email:"jmoiron@jmoiron.net"
}
 _, err = db.NamedExec(`INSERT INTO person (first_name,last_name,email) VALUES (:first,:last,:email)`, dude)

据我所知,本机没有驱动程序提供命名参数。我个人使用它可以绑定来自结构或映射的查询:

_, err = dbm.Select(&users,
    "select * from PersistentUser where mykey = :Key",
    map[string]interface{}{
        "Key": 43,
    }
)


可以创建实现
driver.Valuer{}
map[string]接口{}
类型,将其序列化为
[]字节
,然后将其转换回驱动程序


但这将是低效和不符合实际的。因为你的驱动程序会以非标准的方式使用,最好还是忘记数据库/sql,编写一个带有完全自定义界面的包。

我的问题正好相反——如何将参数作为映射输入。我编辑了一个问题,其中详细介绍了如何插入TupleTool——我仍然希望有人能展示如何使用本机数据库/sql包。谢谢大家提到这一点,这很巧妙。我希望能找到一种使用本机数据库/sql包的方法。您不能使用本机数据库/sql。现有的答案似乎假设您正在编写客户端,但在我看来,您似乎正在编写驱动程序。是的,数据库/sql包是围绕位置参数而不是命名参数构建的。因此,任何让它使用命名参数的解决方法,几乎从定义上来说都是单向的。我开始这个项目已经一个月了。不过,实现的查询语言使用命名参数(这是惯用的方法)。实现的主要问题是,它们需要通过driver.Value类型,而不是接口{}推送。我不知道
db.Prepare
方法的背后到底是什么,但据我所知,您正试图创建一个SQL查询对象,并以OO方式添加参数,因此,您可以传递要在
WHERE
子句中使用的值(作为示例)。MS SQL中有一个名为
sp_executesql
的存储过程,它可以获取带有占位符标记的参数值的SQL语句,然后从变量中填充定义的参数值。甲骨文应该有同样的东西。如果这是在所有接近你正在寻找的,我可以有一个进一步的研究。
_, err = dbm.Select(&users,
    "select * from PersistentUser where mykey = :Key",
    User{Key: 43},
)