首页 > 解决方案 > 无法运行 INSERT 查询,因为 db 已锁定 - SQLite

问题描述

我已经对此进行了两天的故障排除,并且不知所措。

我有这段代码,其中一个 SELECT 查询在一个表中运行,然后如果令牌与数据库中的那个匹配,它将在另一个表上运行一个 INSERT 查询。

SELECT 查询工作得很好,但是,无论我以哪种方式执行 INSERT 查询,它总是会抛出一个 db is locked 错误。

我尝试使用执行 INSERT 查询

了解它也可能没有完成我也尝试过的 SELECT 查询

代码

<?php

error_reporting(E_ALL);
ini_set('display_errors', 1);

$db = new SQLite3('../grasscar_test.sqlite');

$token = $_POST['token'];

$res = $db->query("SELECT key FROM admin WHERE key = '$token'");

if ($res === FALSE){
    echo '{"correct":"no"}';
}

while ($row = $res->fetchArray()){
    $key = "{$row['key']}";

    if ($key === $token){
        //generate token
        $cookieog = openssl_random_pseudo_bytes(32);
        $cookie = bin2hex($cookieog);
        //respond with token
        echo '{"correct":"yes","token":"'.$cookie.'"}';
        //get expiary time
        $expiary = date("Y-m-d H:i:s", strtotime("+30 minutes"));
        //add token and expiary date
        
        $insert = $db->exec("INSERT INTO admin_cookie (cookie, expiary) VALUES ('$cookie', '$expiary')"); //This is the line throwing the error
        print_r($insert);
        
    }else{
        echo '{"correct":"no"}';
    }

}

$db->close();

?>

标签: phpsqlite

解决方案


警告

您的查询不安全且易受 SQL 注入攻击。请参阅https://www.php.net/manual/en/sqlite3.prepare.php了解如何执行准备好的语句或如何防止 PHP 中的 SQL 注入?. $token需要绑定,而不是直接放入查询字符串。或者您可以逃避$token, 但绑定更好的 IMO 并最终得到更清晰的代码 IMO。

选项1

您可以将整体SELECT放入一个数组中,然后显式关闭打开的连接或光标SELECT

while ($row = $res->fetchArray()){
    $resultsArray[] = $row;
}
$res->finalize();
foreach ($resultsArray as $row){
    // your existing code
}

选项 2:非加密安全随机

如果您不需要将所有内容打印到屏幕上,并且您不需要加密安全的随机性,您也可以将它们全部放入一个查询中。我找不到任何东西可以在 sqlite 中产生加密随机性(在几分钟的搜索中)。

INSERT INTO admin_cookie (cookie, expiary) 
SELECT hex(randomblob(32)), datetime('now', '+30 minutes')

附言

  • 你可以试试pdo。很确定它支持 sqlite,你可能更喜欢这个界面。
  • 与其INSERT在循环中 ing,不如构建一个VALUES列表,然后执行一条INSERT语句。但是,使用绑定参数时会有点痛苦(尽管通过增加占位符的名称并在构建 VALUES 列表时构建绑定数组完全可行)
  • 您可能确实需要加密安全的随机性,因此选项 2 并不理想。无论如何,我都不是安全专家。

推荐阅读