2009-08-20 18 views
4

我想在某个时间的Perl下SQLite数据库上做VACUUM,但它总是说

DBD :: SQLite的:: DB做失败:不能从一个事务中真空

那么,我该如何做到这一点?

my %attr = (RaiseError => 0, PrintError => 1, AutoCommit => 0); 
my $dbh = DBI->connect('dbi:SQLite:dbname='.$file'','',\%attr) 
    or die $DBI::errstr; 

我正在使用AutoCommit => 0。并且错误发生时:

$dbh->do('DELETE FROM soap'); 
$dbh->do('DELETE FROM result'); 
$dbh->commit; 
$dbh->do('VACUUM'); 
+1

 my %attr = ( RaiseError => 0, PrintError => 1, AutoCommit => 0); my $dbh = DBI->connect('dbi:SQLite:dbname='.$file'','',\%attr) or die $DBI::errstr; 
我使用自动提交=> 0。 而错误发生时:
 $dbh->do('DELETE FROM soap;'); $dbh->do('DELETE FROM result;'); $dbh->commit; $dbh->do('VACUUM'); 
Galaxy 2009-08-20 01:48:45

回答

11

我假设你在连接调用具有AutoCommit => 0因为以下工作:

#!/usr/bin/perl 

use strict; 
use warnings; 

use DBI; 

my $dbh = DBI->connect('dbi:SQLite:test.db', undef, undef, 
    { RaiseError => 1, AutoCommit => 1} 
); 

$dbh->do('VACUUM'); 

$dbh->disconnect; 

你不必放弃交易能够VACUUM:您可以使用,这样AutoCommitVACUUM开启和VACUUMAutoCommit状态恢复到什么是以下。如果您未设置RaiseError,请添加错误检查以品尝。

sub do_vacuum { 
    my ($dbh) = @_; 
    local $dbh->{AutoCommit} = 1; 
    $dbh->do('VACUUM'); 
    return; 
} 

叫它:

do_vacuum($dbh); 
+0

因此,VACUUM需要AutoCommit = 1来禁用事务。 谢谢。 – Galaxy 2009-08-20 01:59:57

+3

+1建议'local $ dbh - > {AutoCommit} = 1;'并且不需要'$ ac'变量。 – pilcrow 2009-08-20 03:00:24

+1

为什么我不知道你可以在*词法*数组和哈希的元素上使用'local'? Perl对我来说仍然有一些惊喜。 :D – 2009-08-20 03:38:46

1

默认情况下,DBI启用了自动提交功能。在连接关闭它:

my $dbh = DBI->connect($dsn, $user, $pass, { AutoCommit => 0 }); 
+1

Chas。我认为你已经扭转了局面。对于$ dbh-> do('VACCUM')',AutoCommit'需要在事务之外发生。 – 2009-08-20 01:52:45