MySQL IN子句 - 字符串和INT比较

时间:2014-10-22 16:56:17

标签: php mysql stored-procedures

我有一个存储过程,它接受一个String参数 - 传递给this参数的值是一个逗号分隔的来自PHP的ID列表 - 类似于2,3,4,5

`DECLARE tags_in            VARCHAR(255);`

在Stored过程中,我想选择与参数中的id对应的id的行 - 查询就像

`SELECT * from tags WHERE tag_id IN (tags_in)`

我使用以下语句将值从PHP传递到MySQL,将值绑定为字符串

`$stmt->bindParam(':tags', '2,3,4', PDO::PARAM_STR);`

问题 - MySQL执行的实际查询如下 - 传入的参数被视为一个字符串

`SELECT * from tags WHERE tag_id IN ('2,3,4')`

当我想要执行的查询如下所示,其中参数被视为单个整数

`SELECT * from tags WHERE tag_id IN (2,3,4)`

对我的任何建议都可以做到这一点吗?

2 个答案:

答案 0 :(得分:1)

SQL占位符只能表示SINGLE值。如果传入一些以逗号分隔的值,它们将不会被视为带有逗号的多个单独值,它们将被视为单个字符串。

e.g。

... WHERE foo IN (:bar)
... WHERE foo = :bar
就SQL解析器而言,

在功能上是相同的,并且它不会允许传递CSV值。两者都将以相同的方式执行:

... WHERE foo IN ('1,2,3')
... WHERE foo = '1,2,3'

您必须将自己限制为与占位符一样多的值,或者动态构建SQL并为您尝试放入IN子句的每个值添加占位符。

e.g。

$placeholders = array_fill(0, count($values_to_check) -1, '?');
$in_clause = implode(',', $placeholders);
  /// builds ?,?,?,?,?,....?

$sql = "SELECT ... WHERE foo IN ($in_clause)";
$stmt = $dbh->prepare($sql);
$stmt->execute($values_to_check);

这是一个准备好的陈述落在他们脸上的地方,你必须回到好老“动态构建一些sql”。

答案 1 :(得分:0)

有时,还有另一种方法可以通过将要比较的整数转换为用逗号包围的字符串,然后检查结果是否包含在可能的值列表中(在两边各加一个逗号,以此来获得期望的结果)好)。也许这并不是最有效的性能,但它允许您在单个过程或查询中完成所需的操作。

例如(在您的情况下)这样的方法可能有效:

SELECT * from tags WHERE INSTR (CONCAT(',', tags_in, ','), CONCAT(',', tag_id, ',') );

MySql有点奇怪,因为它在CONCAT函数中进行了从int到char的转换,其他一些数据库则需要显式转换。