多列IN/ANY postgres查询

huangapple go评论152阅读模式
英文:

Multi-column IN/ANY postgres query

问题

示例表模式:

  1. create table t1(
  2. col1 varchar(20),
  3. col2 varchar(20)
  4. );

要求:
获取与数组中提供的任何元组(col1,col2)匹配的行。

SQL:

  1. select * from t1 where (col1, col2) in (('c11', 'c12'), ('c21', 'c22'));

我想使用“database/sql”包和“github.com/lib/pq”驱动程序在Go中编写此查询,这就是我遇到问题的地方。

对于单列IN/ANY查询,我可以很容易地实现。

例如,以下查询

  1. select * from t1 where col1 in ('c11', 'c21');

可以使用以下代码片段实现:

  1. args := []string{"c11", "c21"}
  2. conn.Exec(`select * from t1 where col1 = any($1)`, pq.Array(args))

然而,我无法对多列查询使用类似的方法。
我尝试将pq.Array([][]string)pq.Array([]*pq.StringArray)等作为参数传递,但它们不起作用,并返回以下错误:

  1. input of anonymous composite types is not implemented

对此将不胜感激。

英文:

Sample table schema:

  1. create table t1(
  2. col1 varchar(20),
  3. col2 varchar(20)
  4. );

Requirement:
Fetch rows that match any of the tuples (col1, col2) presented in an array.

SQL:

  1. select * from t1 where (col1, col2) in (('c11', 'c12'), ('c21', 'c22'));

I want to write this query in Go using the "database/sql" package with "github.com/lib/pq" driver, and that is where I am facing the problem.

I can easily do this for single column IN/ANY query.

for example, the following query

  1. select * from t1 where col1 in ('c11', 'c21');

can be achieved with the following code snippet:

  1. args := []string{"c11", "c21}
  2. conn.Exec(`select * from t1 where col1 = any($1)`, pq.Array(args))

However, I could not use similar approach for multi-column query.
I tried passing pq.Array([][]string), pq.Array([]*pq.StringArray) etc. as argument, but they do not work, and fetches the following error:

  1. input of anonymous composite types is not implemented

Will appreciate any help on this.

答案1

得分: 1

你可以这样做:

  1. args := [][]string{{"c11","c21"},{"c21","c22"}}
  2. params := make([]interface{}, len(args)*2)
  3. tuples := make([]string, len(args))
  4. for i := range args {
  5. params[i*2] = args[i][0]
  6. params[i*2+1] = args[i][1]
  7. tuples[i] = fmt.Sprintf("($%d,$%d)", i*2+1,i*2+2)
  8. }
  9. invals := "(" + strings.Join(tuples, ",") + ")"
  10. conn.Exec("SELECT * FROM t1 WHERE (col1,col2) IN " + invals, params...)

对于一个两列的元组,你可以这样做:

  1. conn.Exec(`SELECT * FROM t1 WHERE (col1,col2) IN (
  2. SELECT * FROM json_each_text(json_object($1::text[]))
  3. )`, pq.Array([][]string{{"c11","c21"},{"c21","c22"}}))
英文:

You could do the following:

  1. args := [][]string{{"c11","c21"},{"c21","c22"}}
  2. params := make([]interface{}, len(args)*2)
  3. tuples := make([]string, len(args))
  4. for i := range args {
  5. params[i*2] = args[i][0]
  6. params[i*2+1] = args[i][1]
  7. tuples[i] = fmt.Sprintf("($%d,$%d)", i*2+1,i*2+2)
  8. }
  9. invals := "(" + strings.Join(tuples, ",")) + ")"
  10. conn.Exec("SELECT * FROM t1 WHERE (col1,col2) IN " + invals, params...)

For a two-column tuple you should be able to do the following:

  1. conn.Exec(`SELECT * FROM t1 WHERE (col1,col2) IN (
  2. SELECT * FROM json_each_text(json_object($1::text[]))
  3. )`, pq.Array([][]string{{"c11","c21"},{"c21","c22"}}))

huangapple
  • 本文由 发表于 2021年11月30日 16:36:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/70166409.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定