dongzhang1839 2013-12-18 08:18
浏览 16
已采纳

如何在具有非IN条件的已准备好的SQL语句中将[]切片传递给IN条件?

Imagine you have the following SQL query:

SELECT *
  FROM foo
  WHERE type = ?
    AND subtype IN (?)

And you have the following possible data (we imagine that a user interface can set these data):

var Type int
var SubTypes []int

In the case of SubTypes, we are talking about a multiple choice selection.

Now, the following code won't work:

rows, err := sqldb.Query(`SELECT *
  FROM foo
  WHERE type = ?
    AND subtype IN (?)`, Type, SubTypes)

Because the driver (at least the mysql driver used in this example) doesn't recognise a []slice. Typing to explode it (SubTypes...) doesn't work either, because A) you cannot have more than one exploded parameter and B) even if you could, your SQL only supports a single item ((?)).

  • 写回答

2条回答 默认 最新

  • dongluan1901 2013-12-18 16:22
    关注

    Prepared statements do not work that way, at least not in major DBMS I know. I mean, in Go, the support for prepared statements implemented by database/sql drivers is supposed to use the corresponding facility provided by the underlying DBMS (a driver might opt to simulate such support if it's not provided by the DB engine it interfaces with).

    Now in all the DBMS-s I'm familiar with, the whole idea of prepared statement is that it's processed once by the DB engine and cached; "processed" here means syntax checking, compiling into some DB-specific internal representation and its execution plan figured out. As follows from the term "compiled", the statement's text is processed exactly once, and then each call to the prepared statement just essentially tells the server "here is the ID of that prepared statement I supplied you earlier, and here's the list of actual parameters to use for placeholders it contained". It's like compiling a Go program and then calling it several times in a row with different command-line flags.

    So the solution you have come up with is correct: if you want to mess with the statement text between invocation then by all means use client-side text manipulations1 but do not attempt to use the result of it as a prepared statement unless you really intend to execute the resulting text more than once.

    And to be may be more clear: your initial attempt to prepare something like

    SELECT a, b FROM foo WHERE a IN (?)
    

    supposedly fails at your attempt to supply a set of values for that IN (?) placeholder because commas which would be required there to specify several values are syntax, not parts of the value.

    I think it should still be fine to prepare something like

    SELECT a, b FROM foo WHERE a IN (?, ?, ?)
    

    because it does not break that rule. Not that it's a solution for you…

    See also this and this — studying the latter would allow you to play with prepared statements directly in the MySQL client.


    1 Some engines provide for server-side SQL generation with subsequent execution of the generated text.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)