2008-11-10 78 views
14

我正在尝试为PDO语句的结果编写一个迭代器,但我找不到任何倒回到第一行的方法。我想避免调用fetchAll并存储所有结果数据的开销。是否可以倒带PDO结果?

// first loop works fine 
foreach($statement as $result) { 
    // do something with result 
} 

// but subsequent loops don't 
foreach($statement as $result) { 
    // never called 
} 

是否有正在重置陈述或寻求第一行的一些方法?

回答

10

我敢肯定,这取决于数据库。因此,这是你应该尽量避免的。不过,我认为你可以通过启用buffered queries来实现你想要的。如果这不起作用,你总是可以将结果放入一个fetchAll的数组中。这两种解决方案都会影响您的应用程序性能,因此如果结果集很大,请仔细考虑一下。

8

请参阅slide 31 from this presentation,如果它适用于缓冲查询,则可以执行$statement->rewind()。如果您使用mysql,您可以通过使用PDO_MYSQL_ATTR_USE_BUFFERED_QUERY模拟缓冲查询:

$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); 

@NoahGoodrich指出你SPL。下面是一个总是有效的例子:

$it = new ArrayIterator($stmt->fetchAll()); 
9

我写的这个小类包装了一个PDOStatement。它只存储提取的数据。如果这不起作用,您可以移动缓存来读取和写入文件。

// Wrap a PDOStatement to iterate through all result rows. Uses a 
// local cache to allow rewinding. 
class PDOStatementIterator implements Iterator 
{ 
    public 
     $stmt, 
     $cache, 
     $next; 

    public function __construct($stmt) 
    { 
     $this->cache = array(); 
     $this->stmt = $stmt; 
    } 

    public function rewind() 
    { 
     reset($this->cache); 
     $this->next(); 
    } 

    public function valid() 
    { 
     return (FALSE !== $this->next); 
    } 

    public function current() 
    { 
     return $this->next[1]; 
    } 

    public function key() 
    { 
     return $this->next[0]; 
    } 

    public function next() 
    { 
     // Try to get the next element in our data cache. 
     $this->next = each($this->cache); 

     // Past the end of the data cache 
     if (FALSE === $this->next) 
     { 
      // Fetch the next row of data 
      $row = $this->stmt->fetch(PDO::FETCH_ASSOC); 

      // Fetch successful 
      if ($row) 
      { 
       // Add row to data cache 
       $this->cache[] = $row; 
      } 

      $this->next = each($this->cache); 
     } 
    } 
} 
0

问很久以前,但目前还有另一种解决方案。

方法PDOStatement::fetch()可以接收第二参数,即光标方向,其中一个参数为PDO::FETCH_ORI_*常数中的一个。这些参数仅在PDOStatement使用属性PDO::ATTR_CURSOR作为PDO::CURSOR_SCROLL创建时才有效。

这样你可以导航如下。在docsPDO predefined constants

$sql = "Select * From Tabela"; 
$statement = $db->prepare($sql, array(
    PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, 
)); 
$statement->execute(); 
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_NEXT); // return next 
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_PRIOR); // return previous 
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_FIRST); // return first 
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_LAST); // return last 
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_ABS, $n); // return to $n position 
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_REL, $n); // return to $n position relative to current 

更多信息。

注意:使用PDO::FETCH_BOTH因为是默认值,只需为您的项目自定义它。

相关问题