2009-08-20 64 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