简体   繁体   English

逗号分隔的值在PHP MYSQL中不起作用

[英]Comma-separated values doesn't work in PHP MYSQL

I'm currently facing a difficulty where putting a comma-separated values to a MySQL NOT IN doesn't give me the result I was hoping for. 我目前面临的一个困难是,将逗号分隔的值放到MySQL NOT IN并不能给我我想要的结果。 There must be something I'm missing as I'm unsure what to search for this particular problem. 我不确定要搜索什么来寻找特定的问题,所以肯定有一些我想念的东西。 Running only the MySQL code works, but passing the parameter from another PHP function didn't. 仅运行MySQL代码即可,但是无法从另一个PHP函数传递参数。

Here's the code that's giving me a problem: 这是给我一个问题的代码:

$uid = 1;      
$selected_uids = '1,2';       
$result = $db->retrieveFollowingWithCondition($uid, $selected_uids);

...then somewhere along the code... ...然后在代码中的某处...

public function retrieveFollowingWithCondition($uid, $selected_uids) {
$stmt = $this->conn->prepare("SELECT *
        FROM `friendlist`
        WHERE `uid` = ? AND `buddy_uid` NOT IN (?)
        GROUP BY `buddy_uid`;");
        $stmt->bind_param("is", $uid, $selected_uids);
...}

I've tested just putting '2' in $selected_uids and it actually works. 我已经测试过,只是在$selected_uids放入“ 2”,它实际上可以工作。 But once there's comma involved, the code runs but the $selected_uids are still in the result. 但是一旦涉及到逗号,代码就会运行,但是$selected_uids仍然在结果中。 Not sure this is a bad practice or just needing a minor adjustment to the code. 不确定这是一种不好的做法,还是只需要对代码进行少量调整即可。 Anyway, I'm really looking forward to understand why it's not working for me. 无论如何,我真的很期待了解为什么它对我不起作用。

By using s in bind_param you are telling PHP to treat the entire contents of $selected_uids as a string. 通过在bind_param使用s ,您将告诉PHP将$selected_uids的全部内容视为字符串。 Therefore, " 1,2 " is treated as ('1,2') instead of (1,2) . 因此,“ 1,2 ”被视为('1,2')而不是(1,2) Your problem is that bind_param doesn't support arrays, so support of IN queries is limited . 您的问题是bind_param不支持数组,因此对IN查询的支持是受限制的 There are a number of alternatives to get around this limitation, but since you are dealing with a list of ints, I would probably do a raw string concat. 有许多替代方法可以解决此限制,但是由于您要处理的是整数列表,因此我可能会使用原始字符串concat。

// using is_numeric because is_int("1") === false
$filtered = array_filter('is_numeric', $selected_uids);

// You could also just call array_map('intval', $selected_uids);
// Depending on your needs.
if(!$filtered) {
    return; // No valid values
}
$filteredStr = implode(',', $filtered);

$stmt = $this->conn->prepare("SELECT *
    FROM `friendlist`
    WHERE `uid` = ? AND `buddy_uid` NOT IN ($filteredStr)
    GROUP BY `buddy_uid`;");

Should also be noted: if I were trying to use strings for an IN query, I would likely do the following: 还应注意:如果我尝试对IN查询使用字符串,则可能会执行以下操作:

 $filtered = array_map([$this->conn, 'escape_string'], $queried);
 $inQuery = '\'' . implode('\',\'', $filtered) . '\''; 

I find that notation cleaner and easier than a dynamically generated bind_param format string. 我发现这种表示法比动态生成的bind_param格式字符串更干净,更容易。

You should bind every parameter in IN(...) separately, but method bind_param doesn't support multiple calls. 您应该分别绑定IN(...)中的每个参数,但是方法bind_param不支持多个调用。 There is a nice class that can do this and you can find it on PHP documentation pages: Custom class for multiple bind_param 有一个不错的类可以做到这一点,您可以在PHP文档页面上找到它: 多个bind_param的自定义类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM