PDO mysql:如何知道插入是否成功

111
我正在使用PDO来插入一条记录(MySQL和PHP)。
$stmt->bindParam(':field1', $field1, PDO::PARAM_STR);
$stmt->bindParam(':field2', $field2, PDO::PARAM_STR);
$stmt->execute();

有没有办法知道它是否成功插入了,例如如果该记录未被插入因为它是重复的?

编辑:当然我可以查看数据库,但是我的意思是通过编程的反馈。

7个回答

163

31
不要再这样写了,$value = $stmt->execute(); 如果($value){//真}else{//假} - Ólafur Waage
26
如果您只想执行 $stmt->execute(),可以这样写:if ($stmt->execute()) { //true } - Gavin
2
PDOStatement->execute()PDOStatement->errorCode()是否完全一致?在什么情况下,PDOStatement->errorCode()会有返回值,但是PDOStatement->execute()返回true吗?或者PDOStatement->execute()返回false但是PDOStatement->errorCode()没有返回任何值? - datasn.io
2
但是,即使没有插入新记录,INSERT IGNORE 也会返回 true。 - Koffeehaus
3
这个答案为什么被接受了?“你的常识”的答案是正确的,insert通常会抛出致命错误,你如何使用if()语句来处理这个致命错误? - beginner
显示剩余6条评论

31
考虑到 PDO 的推荐错误模式是 ERRMODE_EXCEPTION,因此没有直接的execute()结果验证将起作用。由于代码执行甚至不会达到其他答案中提供的条件。因此,有三种可能的情况可以处理 PDO 中查询的执行结果:1.如果要告知成功,则无需验证。只需继续程序流程即可。2.为了处理意外错误,请保持相同 - 不需要立即处理代码。如果出现数据库错误,那么会抛出异常,并将上升到站点范围的错误处理程序,最终导致一个常见的 500 错误页面。3.要处理预期的错误(如重复主键),如果您有某个特定的场景来处理此特定错误,则使用 try..catch 运算符。对于普通的 PHP 用户来说,这听起来有点陌生 - 怎么会不验证操作的直接结果呢?-但这正是异常的工作方式-在其他地方检查错误。一次性解决问题。非常方便。因此,在简单的代码中,您根本不需要任何错误处理。只需保持您的代码不变:
$stmt->bindParam(':field1', $field1, PDO::PARAM_STR);
$stmt->bindParam(':field2', $field2, PDO::PARAM_STR);
$stmt->execute();
echo "Success!"; // whatever

如果成功,它会告诉您; 如果出现错误,它将显示您的应用程序为此类情况展示的常规错误页面。

仅在有处理场景的情况下,除了报告错误之外,请将您的插入语句放在 try..catch 操作符中,检查是否是您预期的错误并进行处理;或者 - 如果错误不同 - 重新抛出异常,以便可以通过站点范围的错误处理程序通常方式处理它。以下是我在使用PDO处理错误的文章中的示例代码:

try {
     $pdo->prepare("INSERT INTO users VALUES (NULL,?,?,?,?)")->execute($data);
} catch (PDOException $e) {
    if ($e->getCode() == 1062) {
        // Take some action if there is a key constraint violation, i.e. duplicate name
    } else {
        throw $e;
    }
}
echo "Success!";
在上面的代码中,我们检查特定的错误以采取一些行动,并重新抛出异常以处理任何其他错误(例如,没有这样的表),这将报告给程序员。
然而,如果只是告诉用户诸如“您的插入操作成功”之类的信息,则不需要任何条件

2
"Success" 的意思是什么?是指插入了一行新数据,还是没有出现任何错误? - Martin AJ
3
首先,你永远不应该使用 query() 来进行插入操作。插入意味着有输入,而输入意味着需要进行准备。 - Your Common Sense
你建议使用异常来处理“预期”的错误吗? - Chuck Le Butt
@ChuckLeButt,为了清晰起见,我确实建议在这种情况下捕获异常。 - Your Common Sense
1
使用MySQL,我必须检查$e->errorInfo[1] == 1062以验证插入失败,因为$e->getCode()始终为23000。 - tronman
显示剩余8条评论

9

尝试查看execute的返回值,成功时返回TRUE,失败时返回FALSE


9

如果更新查询使用与当前数据库记录匹配的值,则$stmt->rowCount()将返回0,表示没有行受到影响。如果您使用if( rowCount() == 1 )来测试成功,则会认为更新失败,但实际上更新并未失败,只是值已经存在于数据库中,因此没有任何更改。

$stmt->execute();
if( $stmt ) return "success";

当我尝试使用违反唯一键字段的记录更新时,这种方法对我不起作用。查询返回成功,但另一个查询返回旧字段值。


4
如果您需要插入记录,最好的方法是像这样检查............................. ....................... if($stmt->execute() && ($stmt->rowCount()>0)) - jave.web

8
你可以测试行数。
    $sqlStatement->execute( ...);
    if ($sqlStatement->rowCount() > 0)
    {
        return true;
    }

在编程中,参考文档总是很有帮助的@YourCommonSense。虽然文档中说“这种行为不能保证适用于所有数据库,并且不应该依赖于可移植应用程序”,但它仅限于首先选择,并且其次支持mysql,这也是本篇文章的主题。 - crafter
1
@crafter 正确。它说rowCount()对于SELECT查询可能不可靠(即使在那里,文档也提到了多个查询)。它没有提到DELETEINSERTUPDATE,这些似乎可以正常工作(问题是关于一个INSERT查询的)。然而,我对PDO还很陌生,如果我错了,或者有其他参考资料,请在这里写下来。我很想知道上述3个命令是否存在真正的缺点。 - StanE
除了其自身的不一致性外,这个回答在概念上也是错误的,原因与被接受的答案相同。 - Your Common Sense

1

PDOStatement->execute() 可能会抛出异常

你可以这样做:

try
{
PDOStatement->execute();
//record inserted
}
catch(Exception $e)
{
//Some error occured. (i.e. violation of constraints)
}

1
使用id作为主键,并启用自动增量。
$stmt->execute();
$insertid = $conn->lastInsertId();

增量ID始终大于零,即使是第一条记录,这意味着它将始终返回一个真值作为ID,因为在PHP中,大于零意味着真。

if ($insertid)
   echo "record inserted successfully";
else
   echo "record insertion failed";

如果我在表中不需要自动递增的字段怎么办? - Your Common Sense
谁做的?是你吗?在如此广泛使用的RESTFul API中,自增ID就像是强制性的。 - jumper rbk
为什么有些人不会有主键、自增或其他序列列呢?如果需要验证方法,请添加任何顺序列。如果这个解决方案不适合您,就不要添加它。对我来说,这是一个很好的解决方案,我总是使用一些连续的自增列,这样我就可以测试我的查询是否成功了。 - Samuel Ramzan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接