警告
fetch() 在处理空数据集时不符合 SQL-92 SQLSTATE 标准。
它不会将错误代码类设置为 20 来指示“未找到数据”,而是返回一个类 00,表示成功,并返回 NULL 给调用者。
这还会阻止异常机制触发。
程序员需要在任何 fetch*() 之后显式地为空结果集编写测试,而不是依赖于 RDBMS 的默认行为。
我尝试将其记录为错误,但它被驳回为“按预期工作”。 只是提醒一下。
(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.1.0)
PDOStatement::fetch — 从结果集中获取下一行
$mode
= PDO::FETCH_DEFAULT, int $cursorOrientation
= PDO::FETCH_ORI_NEXT, int $cursorOffset
= 0): mixed从与 PDOStatement 对象关联的结果集中获取一行。 mode
参数确定 PDO 如何返回该行。
mode
控制如何将下一行返回给调用方。此值必须是 PDO::FETCH_*
常量之一,默认为 PDO::ATTR_DEFAULT_FETCH_MODE
的值(默认为 PDO::FETCH_BOTH
)。
PDO::FETCH_ASSOC
: 返回一个以结果集中返回的列名为索引的数组
PDO::FETCH_BOTH
(默认): 返回一个以结果集中返回的列名和 0 索引的列号为索引的数组
PDO::FETCH_BOUND
: 返回 true
并将结果集中列的值分配给使用 PDOStatement::bindColumn() 方法绑定的 PHP 变量
PDO::FETCH_CLASS
: 返回请求类的新的实例,将结果集的列映射到类中的命名属性,并在之后调用构造函数,除非还给出了 PDO::FETCH_PROPS_LATE
。如果 mode
包含 PDO::FETCH_CLASSTYPE(例如 PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE
),则类名将从第一列的值确定。
PDO::FETCH_INTO
: 更新请求类的现有实例,将结果集的列映射到类中的命名属性
PDO::FETCH_LAZY
: 结合 PDO::FETCH_BOTH
和 PDO::FETCH_OBJ
,并返回一个 PDORow 对象,该对象在访问时创建对象属性名称。
PDO::FETCH_NAMED
: 返回一个与 PDO::FETCH_ASSOC
相同形式的数组,只是如果存在多个具有相同名称的列,则由该键引用的值将是行中所有具有该列名的值的数组
PDO::FETCH_NUM
: 返回一个以结果集中返回的列号为索引的数组,从列 0 开始
PDO::FETCH_OBJ
: 返回一个匿名对象,其属性名称对应于结果集中返回的列名
PDO::FETCH_PROPS_LATE
: 当与 PDO::FETCH_CLASS
一起使用时,类构造函数将在从相应的列值分配属性之前调用。
cursorOrientation
对于表示可滚动游标的 PDOStatement 对象,此值确定将返回给调用方的行。此值必须是 PDO::FETCH_ORI_*
常量之一,默认为 PDO::FETCH_ORI_NEXT
。要为您的 PDOStatement 对象请求可滚动游标,您必须在使用 PDO::prepare() 准备 SQL 语句时将 PDO::ATTR_CURSOR
属性设置为 PDO::CURSOR_SCROLL
。
cursorOffset
对于表示可滚动游标的 PDOStatement 对象,对于该对象,cursorOrientation
参数设置为 PDO::FETCH_ORI_ABS
,此值指定要获取的结果集中行的绝对编号。
对于表示可滚动游标的 PDOStatement 对象,对于该对象,cursorOrientation
参数设置为 PDO::FETCH_ORI_REL
,此值指定在调用 PDOStatement::fetch() 之前相对于游标位置要获取的行。
此函数在成功时的返回值取决于获取类型。在所有情况下,如果失败或没有更多行,则返回 false
。
如果属性 PDO::ATTR_ERRMODE
设置为 PDO::ERRMODE_WARNING
,则发出级别为 E_WARNING
的错误。
如果属性 PDO::ATTR_ERRMODE
设置为 PDO::ERRMODE_EXCEPTION
,则抛出 PDOException。
示例 #1 使用不同的获取样式获取行
<?php
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();
/* Exercise PDOStatement::fetch styles */
print "PDO::FETCH_ASSOC: ";
print "Return next row as an array indexed by column name\n";
$result = $sth->fetch(PDO::FETCH_ASSOC);
print_r($result);
print "\n";
print "PDO::FETCH_BOTH: ";
print "Return next row as an array indexed by both column name and number\n";
$result = $sth->fetch(PDO::FETCH_BOTH);
print_r($result);
print "\n";
print "PDO::FETCH_LAZY: ";
print "Return next row as a PDORow object with column names as properties\n";
$result = $sth->fetch(PDO::FETCH_LAZY);
print_r($result);
print "\n";
print "PDO::FETCH_OBJ: ";
print "Return next row as an anonymous object with column names as properties\n";
$result = $sth->fetch(PDO::FETCH_OBJ);
print $result->name;
print "\n";
?>
上面的示例将输出
PDO::FETCH_ASSOC: Return next row as an array indexed by column name Array ( [name] => apple [colour] => red ) PDO::FETCH_BOTH: Return next row as an array indexed by both column name and number Array ( [name] => banana [0] => banana [colour] => yellow [1] => yellow ) PDO::FETCH_LAZY: Return next row as a PDORow object with column names as properties PDORow Object ( [name] => orange [colour] => orange ) PDO::FETCH_OBJ: Return next row as an anonymous object with column names as properties kiwi
示例 #2 使用可滚动游标获取行
<?php
function readDataForwards($dbh) {
$sql = 'SELECT hand, won, bet FROM mynumbers ORDER BY BET';
$stmt = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT)) {
$data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n";
print $data;
}
}
function readDataBackwards($dbh) {
$sql = 'SELECT hand, won, bet FROM mynumbers ORDER BY bet';
$stmt = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_LAST);
do {
$data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n";
print $data;
} while ($row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_PRIOR));
}
print "Reading forwards:\n";
readDataForwards($conn);
print "Reading backwards:\n";
readDataBackwards($conn);
?>
上面的示例将输出
Reading forwards: 21 10 5 16 0 5 19 20 10 Reading backwards: 19 20 10 16 0 5 21 10 5
示例 #3 构造顺序
当对象通过 PDO::FETCH_CLASS
获取时,对象的属性会先被赋值,然后调用类的构造函数。 如果还提供了 PDO::FETCH_PROPS_LATE
,则该顺序会颠倒,即先调用构造函数,然后赋值属性。
<?php
class Person
{
private $name;
public function __construct()
{
$this->tell();
}
public function tell()
{
if (isset($this->name)) {
echo "我是 {$this->name}.\n";
} else {
echo "我还没有名字。\n";
}
}
}
$sth = $dbh->query("SELECT * FROM people");
$sth->setFetchMode(PDO::FETCH_CLASS, 'Person');
$person = $sth->fetch();
$person->tell();
$sth->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'Person');
$person = $sth->fetch();
$person->tell();
?>
以上示例将输出类似以下内容
I am Alice. I am Alice. I don't have a name yet. I am Bob.
警告
fetch() 在处理空数据集时不符合 SQL-92 SQLSTATE 标准。
它不会将错误代码类设置为 20 来指示“未找到数据”,而是返回一个类 00,表示成功,并返回 NULL 给调用者。
这还会阻止异常机制触发。
程序员需要在任何 fetch*() 之后显式地为空结果集编写测试,而不是依赖于 RDBMS 的默认行为。
我尝试将其记录为错误,但它被驳回为“按预期工作”。 只是提醒一下。
有人已经指出 PDO::CURSOR_SCROLL 不受 SQLite 驱动程序支持。 值得注意的是,它也不受 MySQL 驱动程序支持。
事实上,如果您尝试将可滚动游标与 MySQL 语句一起使用,PDO::FETCH_ORI_ABS 参数和传递给 fetch() 的偏移量将被静默忽略。 fetch() 的行为将与正常情况相同,以它们从数据库中获取的顺序返回行。
这实际上一开始非常令人困惑。 即使只作为用户添加的注释在此页面上记录,也绝对值得记录。
在 while 循环中使用 PDO::FETCH_COLUMN 时,仅仅在 while 语句中使用该值是不够的,正如许多示例所示
<?php
while ($row = $stmt->fetch(PDO::FETCH_COLUMN)) {
print $row;
}
?>
如果 5 行的值为 1 2 0 4 5,则上面的 while 循环将在第三行停止,只打印 1 2。 解决方案是显式地测试 false
<?php
while (($row = $stmt->fetch(PDO::FETCH_COLUMN)) !== false) {
print $row;
}
?>
或者使用带有 fetchAll() 的 foreach
<?php
foreach ($stmt->fetchAll(PDO::FETCH_COLUMN) as $row) {
print $row;
}
?>
两者都会正确地打印 1 2 0 4 5。
获取第一个返回结果的快速单行代码。这对于非常基本的查询很有用。
<?php
$count = current($db->query("select count(*) from table")->fetch());
?>php
获取对象时,默认情况下在字段填充后调用类的构造函数。
PDO::FETCH_PROPS_LATE 用于更改行为,使其按预期工作 - 在使用数据填充对象字段之前调用构造函数。
示例
<?php
$a = $PDO->query('select id from table');
$a->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'ClassName');
$obj = $a->fetch();
?>
http://bugs.php.net/bug.php?id=53394
以下是如何使用 PDO SQLite 驱动程序的开发人员的快速说明
PDO SQLite 驱动程序不支持游标,因此使用 PDO::CURSOR_SCROLL 属性在使用 PDO SQLite 驱动程序时将不起作用。例如
<?php
// 假设 $Handle 是一个 PDO 处理程序。
$Statement = $Handle->query( $sqlStatement , array( PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL ) );
?>
更糟糕的是,即使错误模式设置为抛出异常,PDO::prepare 在准备查询失败时也不会抛出异常,而是返回一个布尔值 False!
我不但认为这是一个糟糕的设计选择,而且很遗憾的是,这在手册中没有任何说明——事实上,手册没有明确说明哪些驱动程序支持哪些属性,哪些不支持,因此开发人员只能玩猜谜游戏。
我希望这能为一些开发人员省去一些麻烦。
祝好,
一位之前的发布者指出,当没有结果时,此函数返回 NULL。这不是真的。此函数返回一个空数组。fetchAll() 返回相同的结果。
此外,文档指定了“失败”时的行为,但没有说明“失败”的构成。“失败”可能是函数没有返回结果的地方;也就是说,查询“失败”。然而,“失败”显然是 PDO 错误函数会显示“失败”的情况,例如非法的 SQL 语法或对不存在的表的查询等。空结果不是“失败”。也许这对其他人来说很明显,但对我来说并不明显。
如果你想为记录使用一个新类的实例,你可以使用
<?php
include_once("user.class");
$sth = $db->prepare("SELECT * FROM user WHERE id = 1");
/* 自动创建实例 */
$sth->setFetchMode( PDO::FETCH_CLASS, 'user');
$sth->execute();
$user = $sth->fetch( PDO::FETCH_CLASS );
$sth->closeCursor();
print ($user->id);
/* 或者自己创建实例并使用它 */
$user= new user();
$sth->setFetchMode( PDO::FETCH_INTO, $user);
$sth->execute();
$user= $sth->fetch( PDO::FETCH_INTO );
$sth->closeCursor();
print ($user->id);
?>
因为 MySQL 目前不支持使用游标,所以 $cursor_offset 功能在使用 PDO 访问 MySQL 数据库时无法工作。
如果你尝试在 MySQL 数据库记录集中任意访问特定记录或记录组,你可能需要考虑使用 SELECT 语句的 LIMIT 子句来实现这一点,例如 LIMIT 5,3 用于返回第 6、7 和 8 条记录 - 从索引 5(即第 6 条记录)开始的 3 条记录。
如果你想使用 PDO::FETCH_CLASS,你需要先使用 setFetchMode 设置它,如下所示
$stmt->setFetchMode( PDO::FETCH_CLASS, 'classType', array( '构造函数的参数' );
$object = $stmt->fetch( PDO::FETCH_CLASS );
如果你省略它,PHP 会发生段错误。
这只是关于第二个参数 -cursor_oriantation- 的提醒。
PDO::FETCH_ORI_NEXT :-
获取结果集中下一行。仅对可滚动游标有效。
PDO::FETCH_ORI_PRIOR :-
获取结果集中前一行。仅对可滚动游标有效。
PDO::FETCH_ORI_FIRST :-
获取结果集中第一行。仅对可滚动游标有效。
PDO::FETCH_ORI_LAST :-
获取结果集中最后一行。仅对可滚动游标有效。
PDO::FETCH_ORI_ABS :-
根据结果集中行号获取请求的行。仅对可滚动游标有效。
PDO::FETCH_ORI_REL :-
根据游标在结果集中的当前位置的相对位置获取请求的行。仅对可滚动游标有效。
在使用准备好的语句和 MySQL 时要小心使用 fetch()(我不知道其他数据库的情况)。fetch 不会关闭游标,也不会让你发送任何其他查询,即使你的结果集只有一行。
如果你使用 $statement->fetch(),你还需要在之后使用 $statement->closeCursor(),才能执行其他查询。
或者,你可以使用 $statement->fetchAll(),而不需要 $statement->closeCursor()。
似乎如果你使用 $statement->query() 执行 INSERT 语句,然后使用 $statement->fetch(),你将得到一个异常,提示:SQLSTATE[HY000]: General error。
我花了几个小时试图弄清楚如何使用 PDO 操作 BLOB 字段。
请记住,你不能使用类似以下内容的方式检索 BLOB 数据
<?php
$sql = 'SELECT * FROM sometable LIMIT 1';
$stmt = $dbh->prepare($sql);
$stmt->execute();
$stmt->setAttribute(PDO::FETCH_ASSOC);
$row = $stmt->fetch();
$myFile = $row['file'];
?>
你应该尝试以下方法来代替它
<?php
$sql = "SELECT mime, file FROM sometable LIMIT 1";
$stmt = $dbh->prepare($sql);
$stmt->execute();
$stmt->bindColumn(1, $mime,);
$stmt->bindColumn(2, $file, PDO::PARAM_LOB);
$stmt->fetch();
header('Content-type: '.$mime);
print $file;
?>
注意,以这种方式,“获取模式”将被“覆盖”,并且不会应用 PDO::FETCH_PROPS_LATE
<?php
$sth = $db->prepare("SELECT * FROM user WHERE id = 1");
$sth->setFetchMode( PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'user');
$sth->execute();
$user = $sth->fetch( PDO::FETCH_CLASS );
$sth->closeCursor();
?>
相反,你应该将 fetch() 方法的参数区域留空,就像这样(如果你想使用 setFetchMode() 方法设置获取模式)
<?php
$sth = $db->prepare("SELECT * FROM user WHERE id = 1");
$sth->setFetchMode( PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'user');
$sth->execute();
$user = $sth->fetch();
$sth->closeCursor();
?>
我可以使用 PDO::FETCH_COLUMN 来检索结果的第一列。
$ps->fetch( PDO::FETCH_COLUMN );
在 PHP 5.3.10 的 Postgresql 上运行。
请注意,PDO::ATTR_STRINGIFY_FETCHES 对 MySQL 驱动程序无效。MySQL 将始终返回字符串,因为这是核心 mysql PHP 扩展的行为。见 http://bugs.php.net/bug.php?id=44341
在使用 PDO::FETCH_LAZY 时要小心。它添加了一个名为 queryString 的额外字段。我不确定这是个错误还是功能。我在 Debian Jessie 中使用的是 5.6.17 版本。
查询: 'select 1,2,3'
$row=$smt->fetch(PDO::FETCH_OBJ);
var_dump($row);
object(stdClass)#6 (3) {
["1"]=>
string(1) "1"
["2"]=>
string(1) "2"
["3"]=>
string(1) "3"
}
$row=$smt->fetch(PDO::FETCH_LAZY);
var_dump($row);
object(PDORow)#3 (4) {
["queryString"]=>
string(12) "select 1,2,3"
["1"]=>
string(1) "1"
["2"]=>
string(1) "2"
["3"]=>
string(1) "3"
}
当你对一行进行 SELECT 查询,并想检查它是否存在时,你不需要计算 fetchAll() 的结果,你只需检查 $result->fetch() 是否为 true 即可。
<?php
$bbnq = sprintf("SELECT login
FROM users
WHERE id = %u",27);
try
{ $req = $db_bbn->query($bbnq); }
catch (Exception $e)
{ bbnf_pdo_error($e,__FILE__,__LINE__); }
if ( $r = $req->fetch() )
{ echo "This query has a row result"; }
else
{ echo "This query has an empty result"; }
?>
不要这样做
if($objStatement->fetch()) return $objStatement->fetch();
你想要
if($blah=$objStatement->fetch()) return $blah;
相信我。
我在使用 mssql 的存储过程进行 fetch 时遇到了问题,并遇到了 PDOException
SQLSTATE[IMSSP]: The active result for the query contains no fields
使用类似的准备语句
EXEC [mydb].[stored_procedure_that_returns_select] ?;
解决方案是抑制记录计数
SET NOCOUNT ON; EXEC [mydb].[stored_procedure_that_returns_select] ?;
希望它能帮助你!