以PDO格式重写循环内部的查询

时间:2013-01-17 13:32:00

标签: php mysql pdo

我是PDO的新手,目前正在尝试重写我的所有查询。我在重写时遇到的一个问题就是这个,因为它是在循环内写的:

$search = $_GET['search'];
$code = explode(" ", $search);
$code_count = count($code);

$query = "SELECT * FROM table";

if($search != "")
{
if($code_count == 1)
{
     $query .= " WHERE team LIKE '%".mysql_real_escape_string($search)."%'";
} elseif($code_count > 1)
{   
       for($j=0;$j<$code_count;$j++)
       {
        if($j != 0)
        {
        $query .= " OR "; 
        } else
        {
        $query .= " WHERE team LIKE '%".mysql_real_escape_string($code[$j])."%' OR ";
        }           

                $query .= " team LIKE '%".mysql_real_escape_string($code[$j])."%'";
    }

    $query .= "ORDER BY team ASC";
}
} else
{
$query = "SELECT * FROM table ORDER BY team ASC";
}

$result = mysql_query($query)or die(mysql_error());

使用PDO,我尝试了以下方法。

$query = "SELECT * FROM table";

if($search != "")
{
if($code_count == 1)
{
     $query .= " WHERE team LIKE ?";

         $stmt = $db->prepare($query);
         $stmt->bindValue(1, "%$search%", PDO::PARAM_STR);
         $stmt->execute();
} elseif($code_count > 1)
{   
       for($j=0;$j<$code_count;$j++)
       {
        if($j != 0)
        {
        $query .= " OR "; 
        } else
        {
        $query .= " WHERE team LIKE ? OR ";
        }           

                $query .= " team LIKE ?";

               $stmt = $db->prepare($query);
               $stmt->bindValue(1, "%$code[$j]%", PDO::PARAM_STR);
              $stmt->execute();
    }

    $query .= "ORDER BY team ASC";
}
} else
{
$query = "SELECT * FROM table ORDER BY team ASC";
}

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

这种方法运气不好。我一直收到一条错误信息:“参数号无效:绑定变量数与令牌数不匹配”

有什么想法吗?

谢谢,

兰斯

3 个答案:

答案 0 :(得分:2)

当您未自行分配名称时,绑定参数将被命名为1n。您需要更改此行:

$stmt->bindValue(1, "%$code[$j]%", PDO::PARAM_STR);

对此:

$stmt->bindValue($j + 1, "%" . $code[$j] . "%", PDO::PARAM_STR);

答案 1 :(得分:0)

由于可以将参数数组传递给PDOStatement::execute()而不是手动绑定每个参数,因此可以非常简化整个事情:

$code = explode(' ', $_GET['search']);

$stmt = $db->prepare('
  SELECT   *
  FROM     table
  WHERE    FALSE ' . str_repeat(' OR team LIKE ?', count($code)) . '
  ORDER BY team ASC
');

$stmt->execute($code);

答案 2 :(得分:-1)

您的重写中有几个错误:

  • 在构造查询期间,您正在多次调用prepare / bind / execute。在查询字符串完全构造之后,应该只调用一次prepare,并在查询构造之后调用bind + execute。
  • 在循环的每次迭代中,你向查询添加一个或两个(如果j == 0)参数,但是你尝试每个循环只绑定一个 - 所以这些数字不会相加。

通常,要使用参数查询,您需要遵循以下结构:

  1. 构建您的查询字符串
  2. 准备查询字符串
  3. 每次要运行查询时:
    1. 绑定参数
    2. 执行
  4. 所以你的代码应该是:

    // building query
    if($search != "")
    {
      $query = 'SELECT * FROM table ';
      if($code_count == 1)
      {
        // note: this if is unneccessary, the loop below would generate a good SQL even for code_count 0 or 1
        $query .= "WHERE team LIKE ?";
    
      } elseif($code_count > 1)
      {   
        for($j=0;$j<$code_count;$j++)
        {
          if($j != 0)
          {
            $query .= " OR "; 
          } else
          {
            $query .= " WHERE ";
          }           
    
          $query .= " team LIKE ? ";
        }
    
        $query .= "ORDER BY team ASC";
    }
    } else
    {
      $query = "SELECT * FROM table ORDER BY team ASC";
    }
    
    // preparing
    
    $stmt = $db->prepare($query);
    
    // binding parameters
    if($search != '' && $code_count >= 1) {
      for($j=0;$j<$code_count;$j++){
        $stmt->bindValue($j+1, "%".$code[$j]."%", PDO::PARAM_STR);
      }
    }
    
    // execute
    
    $stmt->execute();
    
    // fetch
    
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);