PDO将数组绑定到Where IN

时间:2014-11-10 14:13:50

标签: php sql-server pdo

我想将一个字符串数组绑定到SQL命令的WHERE IN部分,之后我想在SQL Server上运行它。问题可能是我尝试绑定一个字符串数组而不是一个整数数组。

$totalCount = 
"SELECT referral, COUNT(username) AS cnt FROM accounts
WHERE referral IN ($refIdsPartial) GROUP BY referral";

$ps_totalCounts = $dbh->prepare($totalCount);
$ps_totalCounts->execute();

//loop over total counts
foreach($ps_totalCounts as $row){
    echo "Test<br>";
}

我为你回复了$ refIdsPartial,所以你知道这是什么:

54469c27c687b332339627,54469ba0dec3e703865612,54469c77945c7091266617

它只是一个内爆的字符串/ varchars数组。 我用Managementstudio测试了SQL命令,我可以确保这个SQL命令工作,只要我使用每个String / Varchar的引号。例如:

SELECT referral, COUNT(username) AS cnt FROM accounts
WHERE referral IN ('54469c27c687b332339627','54469ba0dec3e703865612') GROUP BY referral

我的问题:

在上面的代码中,它永远不会进入foreach,因此Query的结果似乎是空的。有什么问题(当然我只测试了应该有结果的查询)?

4 个答案:

答案 0 :(得分:2)

你可以使用一些字符串操作。

您可以使用count ? str_repeat("?", count(explode(",", $refIdsPartial)))您需要的$totalCount = "SELECT referral, COUNT(username) AS cnt FROM accounts WHERE referral IN (". str_repeat("?,", count(explode(",", $refIdsPartial))-1) . "?) GROUP BY referral"; 个数。这将创建占位符。

,

现在占位符已就位,您可以从字符串中分解$ps_totalCounts->execute( explode(",", $refIdsPartial) ); 并执行

{{1}}

答案 1 :(得分:0)

以下是我尝试使用数组实现IN语句时使用的代码段。

这是动态的,所以无论你有一个2或200的数组,它都应该按预期执行。

$ids = array(1,2,3);
$in  = str_repeat('?,', count($ids) - 1) . '?';
$sql = "SELECT * FROM table WHERE column IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($ids);
$data = $stm->fetchAll();

您的代码将如下所示:

$refIdsPartial = array('54469c27c687b332339627','54469ba0dec3e703865612','54469c77945c7091266617');
$in  = str_repeat('?,', count($refIdsPartial ) - 1) . '?';
$totalCount = "SELECT referral, COUNT(username) AS cnt FROM accounts WHERE referral IN ($in) GROUP BY referral";
$ps_totalCounts = $dbh->prepare($totalCount);
$ps_totalCounts->execute();

//loop over total counts
foreach($ps_totalCounts as $row)
{
    echo "Test<br>";
}

答案 2 :(得分:0)

您可以使用为您解析sql字符串的包装器方法:

所以当我进行查询时,我总是这样写:

$sql="SELECT * from TableA where account=:account_id and categories in(:categories_list)"

然后,我将其发送到PDO类:

PDO::getAll($sql, array("account_id"=>$_GET["account] , "categories_list"=>explode(",","1,2,3") );

如果您注意到,account_id是一个直接变量,但categories_list将是一个数组,因此包装器需要解析它并检查这些值是否为数组。

然后包装器解析数组并创建binbing元素。因为你可以看到我没有&#34;:account_id&#34;等...将自动分配该符号,以便pdo绑定工作。

我有很多不同的方法,具体取决于我是否需要mysql的所有结果或只是一行或只是一个单元格,但在这种情况下我使用我的make getAll方法是这样的:

public static function getAll($query,$array=array()){
$me=self::getInstance();
if(self::execute($query,$array)){ $resultset = $me->statement->fetchALL(PDO::FETCH_ASSOC); }else{$resultset=false;}
return $resultset;
}

所以当你调用它时,它将调用execute方法,如下所示:

private static function execute($query,$array){
$me=self::getInstance();

$query_array=$array;
$multibind_array=array();

foreach ($query_array as $key => $value) { 
    if(strpos($query, ":".$key)){
        $query_array[":".$key] = $query_array[$key]; 

    if(is_array($query_array[$key]) ){ 

    $multibind_array[":".$key]="";
    foreach($query_array[$key] as $bindKey=>$multibind){
        $bind_id=(":__".$key).$bindKey;
        $multibind_array[":".$key][]=$bind_id;
        $query_array[$bind_id]=$multibind;
    }

$query = str_replace(":".$key, implode(",",$multibind_array[":".$key]) ,$query ); unset($query_array[":".$key]);

    }  
    } unset($query_array[$key]); 
     } //auto prepair array for PDO

$me->dbh->exec("set names utf8");
$me->statement = @$me->dbh->prepare($query); //Verify if this token really match those fieds

try{$me->result=$me->statement->execute($query_array);}
catch(Exception $e){
    $me->result=false;
    echo "PDO error ";
    print_r($me->statement->errorInfo()) ;
}

$me->lastError=$me->statement->errorInfo()[2];
return $me->result;
}

如您所见,数组将附加&#34;:&#34;符号由它自己组成,当它是一个数组时,它会分配相同的占位符但附加一个id,然后用原来的字符串替换原始查询,这些id将在稍后匹配我提供的数组。

最后我们节省了大量的时间,因为你几乎可以直接编写SQL代码,并且可以从PDO中获益。

PDO::getAll($sql, array("account_id"=>$_GET["account] ,"categories_list"=>explode(",","1,2,3") );部分我可以提供我最终没有在sql中使用的值,包装器将找到并排除它。因此我们可以直接从单个更新对象使用相同的数据执行许多不同的mysql操作。

$update_obj=array("id"=>1, "name"=>"test", "account"=>"10");

PDO::doQuery("UPDATE ... name=:name" , $update_obj ); 

这个mysql只更新名称。在正常情况下,PDO会告诉您错误,因为绑定值&#34;帐户&#34;或&#34; id&#34;与查询中找到的相同令牌不匹配。

答案 3 :(得分:0)

我面临类似的问题,需要绑定相当大的数组。我没有跳过绑定并直接注入整个数组来查询或通过动态生成多个唯一占位符来绑定每个数组记录来制作变通方法,而是使用了find_in_set mysql函数。 Read more here

在你的情况下,它将是:

$totalCount = 
"SELECT referral, COUNT(username) AS cnt FROM accounts
WHERE find_in_set(referral,$refIdsPartial) GROUP BY referral";