如何在 PHP 上提交 SQLite3 更新


How to commit SQLite3 updates on PHP?

我正在尝试在PHP中使用SQLite3,在我需要执行UPDATE之前一切都很好。我怀疑我错过了提交,但我找不到如何做到这一点的方法。

我的代码是:

$respostes = $_POST['respostes'];
$return = array();
$conn = new SQLite3( '/home/pi/boxberry/boxberry.db', SQLITE3_OPEN_READWRITE );
$res = $conn->query( 'SELECT numero, resposta FROM preguntes WHERE NOT correcta' );
while( $resposta = $res->fetchArray( SQLITE3_ASSOC ) )
{
    if( strstr( strtolower( $respostes ), strtolower( $resposta['resposta'] ) ) !== FALSE )
    {
        $conn->exec( 'UPDATE preguntes SET correcta = 1 WHERE numero = ' . $resposta['numero'] );
        $return['canvis'] = $conn->changes();
        $conn->exec( 'COMMIT' );
        $res = $conn->query( 'SELECT correcta FROM preguntes WHERE numero = ' . $resposta['numero'] );
        $tmp = $res->fetchArray( SQLITE3_ASSOC );
        $return['tmp'] = $tmp['correcta'];
    }
}
.... more stuff ...
echo json_encode( $return );

我想要的是读取数据库中的所有问题,并将resposta列中的答案与 POST 收到的$respostes变量中的答案进行比较。这也很好用。然后,如果答案是正确的,我需要将此正确性放入数据库,将此行的correcta列设置为 1。如果我显示查询,然后将其放在 SQLite3 控制台上,它可以正常工作,但是当我在 PHP 上重新检查它时,它仍然是 0,即使$conn->changes()显示 UPDATE 影响了 1 行。

检查了我能想到的一切,boxberry.db文件可以被任何用户读取和写入,我尝试使用应该作为默认值的SQLITE3_OPEN_READWRITE来反对它,我试图添加 commit 的执行,甚至将其放在同一个 exec 行中,用分号分隔两者......不会引发错误,但值不会更改。

将SQLite与Python一起使用,我发现我需要在UPDATE之后提交,但是我找不到在PHP中执行此操作的方法。

此脚本返回类似以下内容:{"Canvis":1,"TMP":0}这意味着它应该是 1 个更改,但是当应该是 1 时,数据库中的值仍然是 0。

我建议为此使用PDO而不是SQLite3扩展:

$dbh = new PDO('sqlite:/home/pi/boxberry/boxberry.db');
$res = $dbh->query('SELECT numero, resposta FROM preguntes WHERE NOT correcta');
foreach($res as $resposta)
{
  if(FALSE !== strstr(strtolower($respostes), strtolower($resposta['resposta'])))
  {
    $updstmt = $dbh->prepare('UPDATE preguntes SET correcta = 1 WHERE numero = :numero');
    $updstmt->bindParam(':numero', $resposta['numero']);
    $updstmt->execute();
    $return['canvis'] = $updstmt->rowCount();
    $stmt = $dbh->prepare('SELECT correcta FROM preguntes WHERE numero = :numero');
    $stmt->bindParam(':numero', $resposta['numero']);
    $stmt->execute();
    $return['tmp'] = $stmt->fetchAll();
  }
}

这是未经测试的,但应该可以作为 OP 示例代码的直接替代品。

通过使用 PDO,您不必关心 SQLite 中的提交语句,因为它们是自动处理的。如果您希望能够提交或回滚一组特定的查询,则可以使用 PDO::beginTransactioncommit()/rollBack()

您不需要使用 SQLite3 扩展手动提交更改,但您可能需要使包含数据库文件的目录可写(可能将其设置为您的 Web 服务器软件具有写入权限)。仅仅使数据库文件本身可写对于SQLite来说并不总是足够的。