duanen19871021 2015-08-18 02:22
浏览 122
已采纳

Postgres查询中的generate_series的占位符返回未知

I try to make a query with placeholders like this

database.Query("select login,displayname from (select distinct $1+trunc(random()*$2)::integer as id from generate_series($3,$4) g ) r join users using(id) limit 10",min_id,max_id-min_id,min_id,max_id)

It throws me an error:

pq: function generate_series(unknown, unknown) is not unique

Then I find a solution to format query as a string

query:=fmt.Sprintf("select login,displayname from (select distinct %v+trunc(random()*%v)::integer as id from generate_series(%v,%v) g ) r join users using(id) limit 10",min_id,max_id-min_id,min_id,max_id)

and it works.

I'd like to make it work in a right way, but I don't understand why it doesn't.

Updated:

var min_id int64
var max_id int64
err:=_database.QueryRow("select min(id),max(id) from users").Scan(&min_id, &max_id)
if err!=nil { 
    log.Panicf("Failed to get min and max %v",err.Error())
    return
}

var rows *sql.Rows

query:=fmt.Sprintf("select login,displayname from (select distinct %v+trunc(random()*%v)::integer as id from generate_series(%v,%v) g ) r join users using(id) limit 10",min_id,max_id-min_id,min_id,max_id)
log.Printf(query)
rows,err=_database.Query("select login,displayname from (select distinct $1+trunc(random()*$2)::integer as id from generate_series($3,$4) g ) r join users using(id) limit 10",min_id,max_id-min_id,min_id,max_id)
if err!=nil {
    log.Panicf("failed to get random entries: %v",err)
}
  • 写回答

1条回答 默认 最新

  • duanpang2751 2015-08-18 12:34
    关注

    Try breaking your query apart. You'll see the first part works fine:

    db.QueryRow("SELECT $1+trunc(random()*$2) as test", 10, 5)
    

    This probably works because $1 and $2 are used with mathematical operators (and/or because trunc() and random() both return numbers), so postgres can infer the data type.

    So it looks like it's the generate_series() parameters that aren't being properly determined. Postgres can infer data types based on parameters, e.g.

    if err := db.QueryRow("SELECT trunc($1,2) as test", 1.4343).Scan(&output); err != nil {panic(err)}
    // output = 1.43
    

    However, if it's a polymorphic function ambiguity can arise and it will fail, e.g.

    if err := db.QueryRow("SELECT trunc($1) as test", 1.4343).Scan(&output); err != nil {panic(err)}
    // panic: pq: function trunc(unknown) is not unique
    

    To avoid ambiguity, explicitly cast parameters in your prepared statement, like: generate_series($3::int,$4::int)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 数字取证课程 关于FAT文件系统的操作
  • ¥15 如何使用js实现打印时每页设置统一的标题
  • ¥15 安装TIA PortalV15.1报错
  • ¥15 能把水桶搬到饮水机的机械设计
  • ¥15 Android Studio中如何把H5逻辑放在Assets 文件夹中以实现将h5代码打包为apk
  • ¥15 使用小程序wx.createWebAudioContext()开发节拍器
  • ¥15 关于#爬虫#的问题:请问HMDB代谢物爬虫的那个工具可以提供一下吗
  • ¥15 vue3+electron打包获取本地视频属性,文件夹里面有ffprobe.exe 文件还会报错这是什么原因呢?
  • ¥20 用51单片机控制急停。
  • ¥15 孟德尔随机化结果不一致