golang slice in mysql query with where in clause

人盡茶涼 提交于 2021-02-07 11:43:05

问题


I am trying to run query like below , but only first id value returns :-

select * from `table` where table`.`id` in ('1', '2', '3', '4', '5', '6', '7', '9', '11', '13', '14', '15', '17') and `table`.`deleted_at` is null

I have done following :-

var aID = make([]string, 0)
var in india // india is struct

for rows.Next() {
    cook := rows.Scan(&in.ID)

    aID = append(aID, strconv.Itoa(in.ID))
}

asID = strings.Join(aID, ",")

anotherRow,err := db.Query("SELECT * from table2 where id in (?)", asID)
if err != nil { fmt.Printf("Error: ", err) }
// ... Other line follows up with "for anotherRow.Next() and fetching"

While fetching data, it only returns value of "1" and ignores all other ID passed on with him, which are '2', '3', '4', '5', '6', '7', '9', '11', '13', '14', '15', '17'.

How can i pass it correctly ?

I am using go-sql-driver/mysql.

FAQ :

  1. aID does contain all those numbers as string and

  2. table has all the rows available with provided above id.

  3. table is from where id is fetched and appended to aID and another records with id stored in aID are fetched with in statement from table2.

Thanks


回答1:


You can do something like this:

args := make([]interface{}, len(asID))
for i, id := range asID {
    args[i] = id
}
stmt := `SELECT * from table2 where id in (?` + strings.Repeat(",?", len(args)-1) + `)`
anotherRow, err := db.Query(stmt, args...)

Just note you will want to put in a guard if asID can ever have len == 0.

If you have any other arguments to pass in, you'll have to add them to the args slice.

Also to note, you should explicitly name the columns you want so you can guarantee you are scanning in the correct columns to the correct fields.




回答2:


Try

q,args,err := sqlx.In("SELECT * FROM table2 WHERE id IN(?);", asID) //creates the query string and arguments
rows, err := db.Query(q,args...)

You could also use the Masterminds/squirrel package:

import sq "github.com/Masterminds/squirrel"

...

users := sq.Select("*").From("table2")
active := users.Where(sq.Eq{"id":[]string{"1","2","3"}})
sql, args, err := active.ToSql()

Which will do the in clause automatically when using sq.Eq struct with a slice.




回答3:


example:

idAry := []string{"1", "2", "3"}
ids := strings.Join(idAry, "','")
sqlRaw := fmt.Sprintf(`SELECT * FROM table WHERE id IN ('%s')`, ids)
rows, err := db.Query(sqlRaw)

It works fine




回答4:


The most elegant solution for queries to make array/slice work directly with sql queries. This also sql injection proof as you are not using string concatenation rather using sql prepared statement

idAry := []string{"1", "2", "3"}
q := "SELECT * FROM table WHERE id = any($1);"
rows, err := db.Exec(q, pq.Array(authors))



回答5:


Since you're dealing with ids from your own database and if you are certain there is no way someone could inject malicious "ids" into that code, don't use the placeholder ? and just use the fmt package.

fmt.Sprintf("SELECT * from table2 where id in (%s)", asID)

this will result in SELECT * from table2 where id in (1,2,3,4...) as opposed to SELECT * from table2 where id in ('1,2,3,4...')



来源:https://stackoverflow.com/questions/45351644/golang-slice-in-mysql-query-with-where-in-clause

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!