【问题标题】:Can I bind an array to an IN() condition in a PDO query?我可以将数组绑定到 PDO 查询中的 IN() 条件吗?
【发布时间】:2009-05-28 11:17:57
【问题描述】:

我很想知道是否可以使用 PDO 将值数组绑定到占位符。这里的用例是尝试传递一个值数组以用于IN() 条件。

我希望能够做这样的事情:

<?php
$ids=array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN(:an_array)'
);
$stmt->bindParam('an_array',$ids);
$stmt->execute();
?>

并让 PDO 绑定并引用数组中的所有值。

目前我正在做:

<?php
$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
foreach($ids as &$val)
    $val=$db->quote($val); //iterate through array and quote
$in = implode(',',$ids); //create comma separated list
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN('.$in.')'
);
$stmt->execute();
?>

这确实可以完成这项工作,但只是想知道我是否缺少内置解决方案?

【问题讨论】:

标签: php arrays pdo prepared-statement where-in


【解决方案1】:

您必须构造查询字符串。

<?php
$ids     = array(1, 2, 3, 7, 8, 9);
$inQuery = implode(',', array_fill(0, count($ids), '?'));

$db = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN(' . $inQuery . ')'
);

// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
    $stmt->bindValue(($k+1), $id);

$stmt->execute();
?>

chris (cmets) 和 someoneisintrouble 都建议 foreach 循环 ...

(...)
// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
    $stmt->bindValue(($k+1), $id);

$stmt->execute();

... 可能是多余的,所以 foreach 循环和 $stmt-&gt;execute 可以被替换为 ...

<?php 
  (...)
  $stmt->execute($ids);

【讨论】:

  • 这是一个有趣的解决方案,虽然我更喜欢它迭代 id 并调用 PDO::quote(),但我认为 '?' 的索引如果任何其他占位符首先出现在查询中的其他地方,占位符就会搞砸,对吧?
  • 是的,那会是个问题。但在这种情况下,您可以创建命名参数而不是?。
  • 老问题,但我相信值得注意的是,$foreachbindValue() 不是必需的 - 只需使用数组执行即可。例如:$stmt-&gt;execute($ids);
  • 生成占位符应该像这样str_repeat('?,', count($array) - 1). '?';
  • 只是给那些不知道的人的提示,您不能混合命名参数和未命名参数。因此,如果您在查询中使用命名参数,请将它们切换为 ?,然后增加您的 bindValue 索引偏移量以匹配 IN 的位置?参数。
【解决方案2】:

快速:

//$db = new PDO(...);
//$ids = array(...);

$qMarks = str_repeat('?,', count($ids) - 1) . '?';
$sth = $db->prepare("SELECT * FROM myTable WHERE id IN ($qMarks)");
$sth->execute($ids);

【讨论】:

  • 太好了,我没想过以这种方式使用 input_parameters 参数。对于查询参数多于 IN 列表的查询,可以使用 array_unshift 和 array_push 将必要的参数添加到数组的前端和末尾。另外,我更喜欢$input_list = substr(str_repeat(',?', count($ids)), 1);
  • 你也可以试试str_repeat('?,', count($ids) - 1) . '?'。少了一个函数调用。
  • @erfling,这是一个准备好的语句,注入从哪里来?如果你能用一些实际证据来支持这一点,我将非常乐意做出任何更正。
  • @erfling,是的,这是正确的,绑定参数正是我们在这个例子中所做的,通过发送 execute 一个 id 数组
  • 确实如此。不知何故错过了你正在传递数组的事实。这确实看起来是安全的,也是一个很好的答案。我很抱歉。
【解决方案3】:

使用IN 语句有那么重要吗?尝试使用FIND_IN_SET op.

比如PDO中有这样的查询

SELECT * FROM table WHERE FIND_IN_SET(id, :array)

然后你只需要绑定一个值数组,用逗号内爆,就像这个

$ids_string = implode(',', $array_of_smth); // WITHOUT WHITESPACES BEFORE AND AFTER THE COMMA
$stmt->bindParam('array', $ids_string);

它已经完成了。

UPD:正如一些人在 cmets 中指出的那样,有一些问题应该明确说明。

  1. FIND_IN_SET 没有在表中使用索引,它还没有实现 - 请参阅 this record in the MYSQL bug tracker。感谢@BillKarwin 的通知。
  2. 您不能使用带有逗号的字符串作为数组的值进行搜索。在implode 之后以正确的方式解析此类字符串是不可能的,因为您使用逗号作为分隔符。感谢@VaL 的说明。

好吧,如果您不严重依赖索引并且不使用带逗号的字符串进行搜索,我的解决方案将比上面列出的解决方案更容易、更简单、更快。

【讨论】:

  • IN() 可以使用索引,并算作范围扫描。 FIND_IN_SET() 不能使用索引。
  • 这很重要。我不知道这个。但无论如何,这个问题对性能没有任何要求。对于不太大的表,它比单独的类更好、更干净,用于生成具有不同数量占位符的查询。
  • 是的,但是现在谁的桌子不那么大了? ;-)
  • 这种方法的另一个问题是如果里面会有带逗号的字符串怎么办?例如... FIND_IN_SET(description,'simple,search') 会起作用,但FIND_IN_SET(description,'first value,text, with coma inside') 会失败。所以该函数将搜索"first value", "text", "with coma inside" 而不是所需的"first value", "text, with coma inside"
【解决方案4】:

由于我做了很多动态查询,这是我做的一个超级简单的辅助函数。

public static function bindParamArray($prefix, $values, &$bindArray)
{
    $str = "";
    foreach($values as $index => $value){
        $str .= ":".$prefix.$index.",";
        $bindArray[$prefix.$index] = $value;
    }
    return rtrim($str,",");     
}

像这样使用它:

$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";

返回一个字符串:id1,:id2,:id3,并更新您在运行查询时需要的绑定$bindArray。简单!

【讨论】:

  • 这是一个更好的解决方案,因为它不会破坏参数规则的绑定。这比其他人在这里建议的内联 sql 安全得多。
【解决方案5】:

postgres 非常简洁的方法是使用 postgres-array ("{}"):

$ids = array(1,4,7,9,45);
$param = "{".implode(', ',$ids)."}";
$cmd = $db->prepare("SELECT * FROM table WHERE id = ANY (?)");
$result = $cmd->execute(array($param));

【讨论】:

  • 阻止sql注入?
  • @FábioZangirolami 它是 PDO,所以是的。
  • 需要明确的是,PDO 不保证安全。正确使用准备好的语句可以防止注入攻击。 (在 mysqli 或 pdo 中准备好的语句)
【解决方案6】:

EvilRygy 的解决方案对我不起作用。在 Postgres 中,您可以做另一种解决方法:


$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id = ANY (string_to_array(:an_array, ','))'
);
$stmt->bindParam(':an_array', implode(',', $ids));
$stmt->execute();

【讨论】:

  • 这不起作用:ERROR: operator does not exist: integer = text。至少您需要添加显式转换。
【解决方案7】:

这是我的解决方案:

$total_items = count($array_of_items);
$question_marks = array_fill(0, $total_items, '?');
$sql = 'SELECT * FROM foo WHERE bar IN (' . implode(',', $question_marks ). ')';

$stmt = $dbh->prepare($sql);
$stmt->execute(array_values($array_of_items));

注意array_values 的使用。这可以解决关键排序问题。

我正在合并 id 数组,然后删除重复项。我有类似的东西:

$ids = array(0 => 23, 1 => 47, 3 => 17);

那失败了。

【讨论】:

  • 注意:使用您的解决方案,您可以将项目添加到数组的前面或后面,因此您可以包含其他绑定。 $original_array 在原数组前添加项:array_unshift($original_array, new_unrelated_item); 在原数组后添加项:array_push($original_array, new_unrelated_item); 绑定值时,new_unrelated 项将放置在正确的位置。这允许您混合数组和非数组项。 `
【解决方案8】:

我扩展了 PDO 来做一些类似于 stefs 建议的事情,从长远来看,这对我来说更容易:

class Array_Capable_PDO extends PDO {
    /**
     * Both prepare a statement and bind array values to it
     * @param string $statement mysql query with colon-prefixed tokens
     * @param array $arrays associatve array with string tokens as keys and integer-indexed data arrays as values 
     * @param array $driver_options see php documention
     * @return PDOStatement with given array values already bound 
     */
    public function prepare_with_arrays($statement, array $arrays, $driver_options = array()) {

        $replace_strings = array();
        $x = 0;
        foreach($arrays as $token => $data) {
            // just for testing...
            //// tokens should be legit
            //assert('is_string($token)');
            //assert('$token !== ""');
            //// a given token shouldn't appear more than once in the query
            //assert('substr_count($statement, $token) === 1');
            //// there should be an array of values for each token
            //assert('is_array($data)');
            //// empty data arrays aren't okay, they're a SQL syntax error
            //assert('count($data) > 0');

            // replace array tokens with a list of value tokens
            $replace_string_pieces = array();
            foreach($data as $y => $value) {
                //// the data arrays have to be integer-indexed
                //assert('is_int($y)');
                $replace_string_pieces[] = ":{$x}_{$y}";
            }
            $replace_strings[] = '('.implode(', ', $replace_string_pieces).')';
            $x++;
        }
        $statement = str_replace(array_keys($arrays), $replace_strings, $statement);
        $prepared_statement = $this->prepare($statement, $driver_options);

        // bind values to the value tokens
        $x = 0;
        foreach($arrays as $token => $data) {
            foreach($data as $y => $value) {
                $prepared_statement->bindValue(":{$x}_{$y}", $value);
            }
            $x++;
        }

        return $prepared_statement;
    }
}

你可以这样使用它:

$db_link = new Array_Capable_PDO($dsn, $username, $password);

$query = '
    SELECT     *
    FROM       test
    WHERE      field1 IN :array1
     OR        field2 IN :array2
     OR        field3 = :value
';

$pdo_query = $db_link->prepare_with_arrays(
    $query,
    array(
        ':array1' => array(1,2,3),
        ':array2' => array(7,8,9)
    )
);

$pdo_query->bindValue(':value', '10');

$pdo_query->execute();

【讨论】:

  • 我已经解决了 Mark 评论的第一部分,但正如他所指出的,如果像 :array 这样的标记在查询中的字符串中仍然不安全。
  • 致所有未来读者的注意事项:永远不要使用此解决方案。 断言不适用于生产代码
  • YCS:感谢您的反馈,对您对断言适用性之外的方法的看法感兴趣。
  • 这个想法几乎是一样的,只是没有断言和更直接和明确的方式 - 不是作为单个案例的例外,而是作为构建每个查询的一般方式。每个占位符都标有它的类型。它使猜测(如if (is_array($data)) one)变得不必要,但使数据处理方式更加准确。
  • 致所有阅读 cmets 的人:@Your Common Sense 提到的问题已在 revision 4 中修复。
【解决方案9】:

对我来说,更性感的解决方案是构建一个动态关联数组并使用它

// A dirty array sent by user
$dirtyArray = ['Cecile', 'Gilles', 'Andre', 'Claude'];

// we construct an associative array like this
// [ ':name_0' => 'Cecile', ... , ':name_3' => 'Claude' ]
$params = array_combine(
    array_map(
        // construct param name according to array index
        function ($v) {return ":name_{$v}";},
        // get values of users
        array_keys($dirtyArray)
    ),
    $dirtyArray
);

// construct the query like `.. WHERE name IN ( :name_1, .. , :name_3 )`
$query = "SELECT * FROM user WHERE name IN( " . implode(",", array_keys($params)) . " )";
// here we go
$stmt  = $db->prepare($query);
$stmt->execute($params);

【讨论】:

  • 如果没有在实际场景中尝试就很难确定,但看起来还不错。+1
【解决方案10】:

查看PDO :Predefined Constants,没有您需要的 PDO::PARAM_ARRAY,如PDOStatement->bindParam 中所列

bool PDOStatement::bindParam (mixed $parameter , mixed &$variable [, int $data_type [, int $length [, mixed $driver_options ]]] )

所以我不认为这是可以实现的。

【讨论】:

  • 我不知道这是否有效。我猜想内爆的字符串会被引用。
  • 你是对的,引号会被转义,这样就行不通了。我已删除该代码。
【解决方案11】:

当你有其他参数时,你可以这样做:

$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
$query = 'SELECT *
            FROM table
           WHERE X = :x
             AND id IN(';
$comma = '';
for($i=0; $i<count($ids); $i++){
  $query .= $comma.':p'.$i;       // :p0, :p1, ...
  $comma = ',';
}
$query .= ')';

$stmt = $db->prepare($query);
$stmt->bindValue(':x', 123);  // some value
for($i=0; $i<count($ids); $i++){
  $stmt->bindValue(':p'.$i, $ids[$i]);
}
$stmt->execute();

【讨论】:

  • 感谢您的出色回答。这是唯一一个真正为我工作的。但是,我看到了 1 个错误。变量 $rs 应该是 $stmt
【解决方案12】:

我也意识到这个线程很旧,但我有一个独特的问题,在将即将被弃用的 mysql 驱动程序转换为 PDO 驱动程序时,我必须创建一个可以动态构建普通参数和 IN 的函数来自同一个参数数组。所以我很快建立了这个:

/**
 * mysql::pdo_query('SELECT * FROM TBL_WHOOP WHERE type_of_whoop IN :param AND siz_of_whoop = :size', array(':param' => array(1,2,3), ':size' => 3))
 *
 * @param $query
 * @param $params
 */
function pdo_query($query, $params = array()){

    if(!$query)
        trigger_error('Could not query nothing');

    // Lets get our IN fields first
    $in_fields = array();
    foreach($params as $field => $value){
        if(is_array($value)){
            for($i=0,$size=sizeof($value);$i<$size;$i++)
                $in_array[] = $field.$i;

            $query = str_replace($field, "(".implode(',', $in_array).")", $query); // Lets replace the position in the query string with the full version
            $in_fields[$field] = $value; // Lets add this field to an array for use later
            unset($params[$field]); // Lets unset so we don't bind the param later down the line
        }
    }

    $query_obj = $this->pdo_link->prepare($query);
    $query_obj->setFetchMode(PDO::FETCH_ASSOC);

    // Now lets bind normal params.
    foreach($params as $field => $value) $query_obj->bindValue($field, $value);

    // Now lets bind the IN params
    foreach($in_fields as $field => $value){
        for($i=0,$size=sizeof($value);$i<$size;$i++)
            $query_obj->bindValue($field.$i, $value[$i]); // Both the named param index and this index are based off the array index which has not changed...hopefully
    }

    $query_obj->execute();

    if($query_obj->rowCount() <= 0)
        return null;

    return $query_obj;
}

它仍然未经测试,但逻辑似乎在那里。

希望对处于相同位置的人有所帮助,

编辑:经过一些测试,我发现:

  • PDO 不喜欢 '.'以他们的名义(如果你问我,这有点愚蠢)
  • bindParam 是错误的函数,bindValue 是正确的函数。

将代码编辑为工作版本。

【讨论】:

    【解决方案13】:

    关于 Schnalle 代码的一点编辑

    <?php
    $ids     = array(1, 2, 3, 7, 8, 9);
    $inQuery = implode(',', array_fill(0, count($ids)-1, '?'));
    
    $db   = new PDO(...);
    $stmt = $db->prepare(
        'SELECT *
         FROM table
         WHERE id IN(' . $inQuery . ')'
    );
    
    foreach ($ids as $k => $id)
        $stmt->bindValue(($k+1), $id);
    
    $stmt->execute();
    ?>
    
    //implode(',', array_fill(0, count($ids)-1), '?')); 
    //'?' this should be inside the array_fill
    //$stmt->bindValue(($k+1), $in); 
    // instead of $in, it should be $id
    

    【讨论】:

    • 我必须在 count($ids) 之后删除 -1 才能为我工作,否则总会缺少一个占位符。
    【解决方案14】:

    您使用的是什么数据库?在 PostgreSQL 中,我喜欢使用 ANY(array)。所以要重用你的例子:

    <?php
    $ids=array(1,2,3,7,8,9);
    $db = new PDO(...);
    $stmt = $db->prepare(
        'SELECT *
         FROM table
         WHERE id = ANY (:an_array)'
    );
    $stmt->bindParam('an_array',$ids);
    $stmt->execute();
    ?>
    

    不幸的是,这是非常不便携的。

    在其他数据库上,您需要像其他人所提到的那样创造自己的魔法。当然,您需要将该逻辑放入类/函数中,以使其在整个程序中可重用。查看 PHP.NET 上 mysql_query 页面上的 cmets,了解有关该主题的更多想法和此场景的示例。

    【讨论】:

      【解决方案15】:

      如果列只能包含整数,您可以不使用占位符,直接将 id 放入查询中。您只需要将数组的所有值转换为整数。像这样:

      $listOfIds = implode(',',array_map('intval', $ids));
      $stmt = $db->prepare(
          "SELECT *
           FROM table
           WHERE id IN($listOfIds)"
      );
      $stmt->execute();
      

      这应该不会受到任何 SQL 注入的攻击。

      【讨论】:

        【解决方案16】:

        据我所知,不可能将数组绑定到 PDO 语句中。

        但存在两种常见的解决方案:

        1. 使用位置占位符 (?,?,?,?) 或命名占位符 (:id1, :id2, :id3)

          $whereIn = implode(',', array_fill(0, count($ids), '?'));

        2. 早先引用数组

          $whereIn = array_map(array($db, 'quote'), $ids);

        这两种选择都很好且安全。 我更喜欢第二个,因为它更短,如果需要,我可以 var_dump 参数。 使用占位符您必须绑定值,最终您的 SQL 代码将是相同的。

        $sql = "SELECT * FROM table WHERE id IN ($whereIn)";
        

        最后对我来说重要的是避免错误“绑定变量的数量与标记的数量不匹配”

        Doctrine 是使用位置占位符的一个很好的例子,只是因为它对传入的参数有内部控制。

        【讨论】:

          【解决方案17】:

          在经历了同样的问题之后,我找到了一个更简单的解决方案(尽管仍然没有PDO::PARAM_ARRAY 那样优雅):

          给定数组$ids = array(2, 4, 32)

          $newparams = array();
          foreach ($ids as $n => $val){ $newparams[] = ":id_$n"; }
          
          try {
              $stmt = $conn->prepare("DELETE FROM $table WHERE ($table.id IN (" . implode(", ",$newparams). "))");
              foreach ($ids as $n => $val){
                  $stmt->bindParam(":id_$n", intval($val), PDO::PARAM_INT);
              }
              $stmt->execute();
          

          ...等等

          因此,如果您使用的是混合值数组,则需要更多代码来测试您的值,然后再分配类型参数:

          // inside second foreach..
          
          $valuevar = (is_float($val) ? floatval($val) : is_int($val) ? intval($val) :  is_string($val) ? strval($val) : $val );
          $stmt->bindParam(":id_$n", $valuevar, (is_int($val) ? PDO::PARAM_INT :  is_string($val) ? PDO::PARAM_STR : NULL ));
          

          但我没有测试过这个。

          【讨论】:

            【解决方案18】:

            不能在 PDO 中使用这样的数组。

            您需要为每个值构建一个带有参数(或使用?)的字符串,例如:

            :an_array_0, :an_array_1, :an_array_2, :an_array_3, :an_array_4, :an_array_5

            这是一个例子:

            <?php
            $ids = array(1,2,3,7,8,9);
            $sqlAnArray = join(
                ', ',
                array_map(
                    function($index) {
                        return ":an_array_$index";
                    },
                    array_keys($ids)
                )
            );
            $db = new PDO(
                'mysql:dbname=mydb;host=localhost',
                'user',
                'passwd'
            );
            $stmt = $db->prepare(
                'SELECT *
                 FROM table
                 WHERE id IN('.$sqlAnArray.')'
            );
            foreach ($ids as $index => $id) {
                $stmt->bindValue("an_array_$index", $id);
            }
            

            如果你想继续使用bindParam,你可以这样做:

            foreach ($ids as $index => $id) {
                $stmt->bindParam("an_array_$index", $ids[$id]);
            }
            

            如果你想使用? 占位符,你可以这样做:

            <?php
            $ids = array(1,2,3,7,8,9);
            $sqlAnArray = '?' . str_repeat(', ?', count($ids)-1);
            $db = new PDO(
                'mysql:dbname=dbname;host=localhost',
                'user',
                'passwd'
            );
            $stmt = $db->prepare(
                'SELECT *
                 FROM phone_number_lookup
                 WHERE country_code IN('.$sqlAnArray.')'
            );
            $stmt->execute($ids);
            

            如果您不知道$ids 是否为空,您应该对其进行测试并相应地处理这种情况(返回一个空数组,或者返回一个 Null 对象,或者抛出一个异常......)。

            【讨论】:

              【解决方案19】:

              这是我的解决方案。我还扩展了 PDO 类:

              class Db extends PDO
              {
              
                  /**
                   * SELECT ... WHERE fieldName IN (:paramName) workaround
                   *
                   * @param array  $array
                   * @param string $prefix
                   *
                   * @return string
                   */
                  public function CreateArrayBindParamNames(array $array, $prefix = 'id_')
                  {
                      $newparams = [];
                      foreach ($array as $n => $val)
                      {
                          $newparams[] = ":".$prefix.$n;
                      }
                      return implode(", ", $newparams);
                  }
              
                  /**
                   * Bind every array element to the proper named parameter
                   *
                   * @param PDOStatement $stmt
                   * @param array        $array
                   * @param string       $prefix
                   */
                  public function BindArrayParam(PDOStatement &$stmt, array $array, $prefix = 'id_')
                  {
                      foreach($array as $n => $val)
                      {
                          $val = intval($val);
                          $stmt -> bindParam(":".$prefix.$n, $val, PDO::PARAM_INT);
                      }
                  }
              }
              

              以下是上述代码的示例用法:

              $idList = [1, 2, 3, 4];
              $stmt = $this -> db -> prepare("
                SELECT
                  `Name`
                FROM
                  `User`
                WHERE
                  (`ID` IN (".$this -> db -> CreateArrayBindParamNames($idList)."))");
              $this -> db -> BindArrayParam($stmt, $idList);
              $stmt -> execute();
              foreach($stmt as $row)
              {
                  echo $row['Name'];
              }
              

              让我知道你的想法

              【讨论】:

              • 忘了说这是基于下面user2188977的回答。
              • 我不确定 getOne() 是什么,它似乎不是 PDO 的一部分。我只在 PEAR 中看到过它。它到底是做什么的?
              • @YourCommonSense 你能发布你的用户定义函数作为答案吗?
              • 我建议将数据类型传递给关联数组中的BindArrayParam,因为您似乎将其限制为整数。
              【解决方案20】:

              借助 MySQL 和 PDO,我们可以使用 JSON 数组和 JSON_CONTAINS() (https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains) 进行搜索。

              $ids = [123, 234, 345, 456]; // Array of users I search
              $ids = json_encode($ids); // JSON conversion
              
              $sql = <<<SQL
                  SELECT ALL user_id, user_login
                  FROM users
                  -- Cast is mandatory beaucause JSON_CONTAINS() waits JSON doc candidate
                  WHERE JSON_CONTAINS(:ids, CAST(user_id AS JSON))
                  SQL;
              
              $search = $pdo->prepare($sql);
              $search->execute([':ids' => $ids]);
              $users = $search->fetchAll();
              

              还可以使用JSON_TABLE() (https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html#function_json-table) 进行更复杂的案例和 JSON 数据探索:

              $users = [
                  ['id' => 123, 'bday' => ..., 'address' => ...],
                  ['id' => 234, 'bday' => ..., 'address' => ...],
                  ['id' => 345, 'bday' => ..., 'address' => ...],
              ]; // I'd like to know their login
              
              $users = json_encode($users);
              
              $sql = <<<SQL
                  SELECT ALL user_id, user_login
                  FROM users
                  WHERE user_id IN (
                      SELECT ALL user_id
                      FROM JSON_TABLE(:users, '$[*]' COLUMNS (
                          -- Data exploration...
                          -- (if needed I can explore really deeply with NESTED kword)
                          user_id INT PATH '$.id',
                          -- I could skip these :
                          user_bday DATE PATH '$.bday',
                          user_address TINYTEXT PATH '$.address'
                      )) AS _
                  )
                  SQL;
              
              $search = $pdo->prepare($sql);
              $search->execute([':users' => $users]);
              ...
              

              【讨论】:

                【解决方案21】:

                为了更接近使用占位符绑定参数的原始问题,我更进一步。

                这个答案必须在要在查询中使用的数组中进行两次循环。但它确实解决了使用其他列占位符进行更有选择性的查询的问题。

                //builds placeholders to insert in IN()
                foreach($array as $key=>$value) {
                    $in_query = $in_query . ' :val_' . $key . ', ';
                }
                
                //gets rid of trailing comma and space
                $in_query = substr($in_query, 0, -2);
                
                $stmt = $db->prepare(
                    "SELECT *
                     WHERE id IN($in_query)";
                
                //pind params for your placeholders.
                foreach ($array as $key=>$value) {
                    $stmt->bindParam(":val_" . $key, $array[$key])
                }
                
                $stmt->execute();
                

                【讨论】:

                  【解决方案22】:

                  你先设置了多少个“?”在查询中然后通过“for”发送参数 像这样:

                  require 'dbConnect.php';
                  $db=new dbConnect();
                  $array=[];
                  array_push($array,'value1');
                  array_push($array,'value2');
                  $query="SELECT * FROM sites WHERE kind IN (";
                  
                  foreach ($array as $field){
                      $query.="?,";
                  }
                  $query=substr($query,0,strlen($query)-1);
                  $query.=")";
                  $tbl=$db->connection->prepare($query);
                  for($i=1;$i<=count($array);$i++)
                      $tbl->bindParam($i,$array[$i-1],PDO::PARAM_STR);
                  $tbl->execute();
                  $row=$tbl->fetchAll(PDO::FETCH_OBJ);
                  var_dump($row);
                  

                  【讨论】:

                    猜你喜欢
                    • 2010-10-29
                    相关资源
                    最近更新 更多