连接到 sqlite 文件时强制只读

Force readonly when connecting to sqlite file

在许多前端, 我希望使用到从主服务器镜像的 sqlite3 文件的只读连接来执行我的脚本。

有没有办法让 DBI 做到这一点?

目前,我正在这样做:

       $dbHand = DBI->connect("dbi:SQLite:dbname=$dbName", $dbUser, $dbPass, {
            PrintError => 0,
            RaiseError => 1,
            AutoCommit => 1,
    }) or die $DBI::errstr;

并获得完全访问权限。

刚设置

$dbHand ->{ReadOnly} = 1

如描述here

使用 sqlite_open_flags 属性,如 DBD::SQLite documentation 中所述:

use DBD::SQLite;
my $dbh = DBI->connect("dbi:SQLite:$dbfile", undef, undef, {
  sqlite_open_flags => DBD::SQLite::OPEN_READONLY,
});

如果您尝试打开一个不存在的数据库(通常会创建一个新数据库)或者如果您尝试写入一个现有数据库,这将导致错误。

请注意,您必须显式 use DBD::SQLite; 才能使用常量 DBD::SQLite::OPEN_READONLY


请注意 DBI 提供 ReadOnly 句柄属性,但 DBD::SQLite 在 v1 之前不支持它。49_05:

use strict;
use warnings;

use Data::Dump;
use DBI;

my $db = 'foo.db';
unlink $db if -f $db;

my $dbh = DBI->connect("dbi:SQLite:dbname=$db",'','', {
    RaiseError => 1,
    ReadOnly   => 1
});

$dbh->do( q{CREATE TABLE foo(id INTEGER, name TEXT)} );
$dbh->do( q{INSERT INTO foo VALUES(1, 'foo')} );
my $values = $dbh->selectall_arrayref( q{SELECT * FROM foo} );

dd $values;

输出:

[[1, "foo"]]

切换到 sqlite_open_flags => DBD::SQLite::OPEN_READONLY 会导致错误。

如果数据库不存在:

DBI connect('dbname=foo.db','',...) failed: unable to open database file

如果数据库存在:

DBD::SQLite::db do failed: attempt to write a readonly database

从 DBD::SQLite v1.49_05 开始,您还可以使用 ReadOnly 属性,但只能作为 connect 的选项。连接后设置属性不起作用并引发警告:

my $dbh = DBI->connect("dbi:SQLite:dbname=$db",'','', {
    RaiseError => 1
});
$dbh->{ReadOnly} = 1;

输出:

DBD::SQLite::db STORE warning: ReadOnly is set but it's only advisory