【发布时间】:2017-05-11 20:51:12
【问题描述】:
为什么在VACUUM backup之前声明准备好的语句$stmt2会导致General error: 17 database schema has changed错误?
<?php
require '../vendor/autoload.php';
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
set_time_limit(0);
$db = new \PDO("sqlite:".__DIR__."/../db/datalogger.db");
$db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$db->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
print_r($db->query('SELECT version, polltimeDestination FROM config WHERE bogus=0')->fetch());
$stmt1=$db->prepare('UPDATE config SET polltimeDestination=? WHERE bogus=0');
$stmt1->execute([300]);
$db->exec('DELETE FROM backup');
$stmt2=$db->prepare('UPDATE config SET version=? WHERE bogus=0');
$db->exec('VACUUM backup');
//$stmt2=$db->prepare('UPDATE config SET version=? WHERE bogus=0');
$stmt2->execute([8]);
输出:
stdClass Object ( [version] => 8 [polltimeDestination] => 300 )
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 17 database schema has changed' in /var/www/html/test2.php:26 Stack trace: #0 /var/www/html/test2.php(26): PDOStatement->execute(Array) #1 {main} thrown in /var/www/html/test2.php on line 26
【问题讨论】:
-
我认为这是一个没有任何实际应用的学术问题?
-
@YourCommonSense 虽然没有显示,但真正的应用程序是一个持续运行的服务,我觉得只分配一次准备好的语句更合适。我发布的代码只是创建错误的最低限度的代码。发现错误后,变得有点学术,我只是希望更好地了解发生了什么。
-
有道理。好吧,我不是准备好的语句内部的专家,但我认为错误消息说明了一切:看起来真空被认为是模式更改器,而准备好的语句,就其性质而言,与模式紧密耦合,正在运行一个查询减半。所以,是的,显而易见的解决方法是每次都做好准备。应该没什么大不了的
-
@YourCommonSense 通常在使用循环时,首先创建准备好的语句然后在循环中执行多次是很常见的。除了使用真空,还有其他必须注意的“陷阱”吗?
-
我会说任何架构更改器,例如添加或删除表或列。