为什么模拟准备语句失败?

时间:2011-11-20 10:04:53

标签: php mysql pdo

从PHP manual,它声明:

  

PDO :: ATTR_EMULATE_PREPARES启用或禁用已准备好的仿真   声明。某些驱动程序不支持本机预处理语句或   对他们的支持有限。使用此设置可以强制PDO   始终模拟预准备语句(如果为TRUE),或尝试使用本机语句   准备好的陈述(如果为FALSE)。它将永远回归模仿   准备好的声明,如果司机不能成功准备   当前查询。需要布尔。

我的查询是这样的:

$type = PDO::PARAM_INT;
if($_POST['code'] == "") $type = PDO::PARAM_NULL;

$stmt = $dbh->prepare("UPDATE Product SET code=? WHERE id=?");
$stmt->bindValue(1, $_POST['code'], $type);
$stmt->bindValue(2, $_SESSION['id'], PDO::PARAM_INT);
$stmt->execute();

我意识到如果不设置以下语句,我会使用上面的代码在我的数据库中获得'0'而不是NULL值(当$_POST['code'] == ""时)。为什么会这样?

$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

更新

虽然禁用仿真对我有用,但我更喜欢使用它,因为像question中的OP一样,基本上我的所有查询只在每次执行脚本时执行一次。因此,准备好语句不会给我带来任何好处,并且会对数据库进行不必要的调用,如下面的常规查询日志中所示:

Emulation Disabled
22 Connect user@localhost on Database
22 Prepare UPDATE Product SET code=? WHERE id=?
22 Execute UPDATE Product SET code='abc' WHERE id='123'
22 Close stmt   
22 Quit

Emulation Enabled
22 Connect user@localhost on Database
22 Query UPDATE Product SET code='abc' WHERE id='123'
22 Quit

非常感谢您解决NULL问题的任何帮助。

1 个答案:

答案 0 :(得分:5)

null尝试绑定PDO::PARAM_NULL

$type = PDO::PARAM_INT;
if($_POST['code'] == "") {
    $_POST['code'] = null;
    $type = PDO::PARAM_NULL;
}

$stmt = $dbh->prepare("UPDATE Product SET code=? WHERE id=?");
$stmt->bindValue(1, $_POST['code'], $type);
$stmt->bindValue(2, $_SESSION['id'], PDO::PARAM_INT);
$stmt->execute();

事实上,您似乎不需要使用PDO::PARAM_NULL,下面的代码也会插入null

$stmt->bindValue(1, $_POST['code'] ? $_POST['code'] : null, PDO::PARAM_INT);