SQL + goLang - 运行带有IN条件的select语句 - 并传递一个id数组?

时间:2018-06-01 20:53:09

标签: mysql sql go

我想执行以下逻辑 -

SELECT some_column
FROM table_name
WHERE id IN (value1, value2, ...);

在我的go代码中,我有以下int数组来表示我的ID:

idsToGet := []int{1,2}

我完全理解你通常会做一个sprintf并传入你正在寻找的一个id ......但是......

我觉得有一种合理的方法可以在不迭代数组的情况下执行此操作,并将此作为每个ID的单独调用...通过sprintf - 有一种方法可以做到这一点只需一个调用 - 和让我的IN子句自动包含我的数组中的所有内容吗?

Go的新手 - 一直试图解决这个问题一小时,我让它适用于单身人士 - 但不适用于倍数。

1 个答案:

答案 0 :(得分:2)

您不想使用Sprintf将原始值放入SQL中,这是一个坏习惯。你想要做的是用适当数量的占位符构建一些SQL,然后让库负责用它们的值替换占位符。

如果你的数组中有两个int,那么你想构建它:

SELECT some_column
FROM table_name
WHERE id IN (?, ?)

如果您有四个,那么您想要构建:

SELECT some_column
FROM table_name
WHERE id IN (?, ?, ?, ?)

等等。您所需要的只是一个简单的函数,可以生成n个占位符;有很多方法可以做到这一点:

func placeholders(n int) string {
    ps := make([]string, n)
    for i := 0; i < n; i++ {
        ps[i] = "?"
    }
    return strings.Join(ps, ",")
}

或者也许:

func placeholders(n int) string {
    var b strings.Builder
    for i := 0; i < n - 1; i++ {
        b.WriteString("?,")
    }
    if n > 0 {
        b.WriteString("?")
    }
    return b.String()
}

或者对您而言最清楚的是,只要它是正确的,实施就不会产生任何可衡量的影响。

然后你可以这样说:

query := fmt.Sprintf("select some_column from table_name where id in (%s)", placeholders(len(idsToGet)))
rows, err := db.Query(query, idsToGet...)

并以通常的方式旋转rows