SQLite – Perl

下面是一份 完整的 SQLite + Perl 中文教程,涵盖从环境搭建到 CRUD 操作、事务、连接管理等实用技巧,适合初学者和进阶开发者。


一、SQLite 简介

SQLite 是一个轻量级、嵌入式、零配置的数据库引擎,适合:

  • Web 应用(Perl 项目)
  • 脚本自动化
  • 嵌入式系统
  • 本地数据存储

它将整个数据库保存在 单个文件 中,无需服务器。Perl 通过 DBI 和 DBD::SQLite 模块实现支持。


二、Perl 环境要求

  • Perl 版本:5.8.0 或更高(推荐 Perl 5.36+)
  • 安装模块
  • DBI:数据库接口(通常已内置)。
  • DBD::SQLite:SQLite 驱动(最新版本 1.72,2024 年发布,捆绑 SQLite 3.46.0)。
  • 安装步骤(使用 cpanm,推荐):
  cpanm DBI DBD::SQLite

或使用 cpan:

  cpan DBI
  cpan DBD::SQLite
  • 验证安装
  #!/usr/bin/perl
  use strict;
  use warnings;
  use DBI;

  eval { require DBD::SQLite; };
  if ($@) {
      die "DBD::SQLite 未安装: $@\n";
  }
  print "DBD::SQLite 已安装!SQLite 版本: " . DBD::SQLite::sqlite_version() . "\n";

运行:perl check.pl,应显示类似 “3.46.0”。

手动下载:https://metacpan.org/pod/DBD::SQLite


三、Perl 连接 SQLite 数据库

#!/usr/bin/perl
use strict;
use warnings;
use DBI;

my $db_file = 'users.db';
my $dsn = "DBI:SQLite:dbname=$db_file";

# 连接数据库
my $dbh = DBI->connect($dsn, '', '', {
    AutoCommit => 1,
    RaiseError => 1,
    PrintError => 0,
    sqlite_unicode => 1  # 支持 UTF-8
}) or die "连接失败: " . $DBI::errstr;

print "成功连接 SQLite 数据库!\n";

# 创建表
$dbh->do(q{
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        age INTEGER NOT NULL
    )
}) or die "创建表失败: " . $DBI::errstr;

print "表 'users' 已创建或已存在。\n";

# 插入数据
my $sth = $dbh->prepare("INSERT INTO users (name, age) VALUES (?, ?)")
    or die "准备插入失败: " . $DBI::errstr;
$sth->execute('张三', 28) or die "插入失败: " . $DBI::errstr;
$sth->execute('李四', 35) or die "插入失败: " . $DBI::errstr;
print "已插入数据。\n";

# 查询数据
$sth = $dbh->prepare("SELECT id, name, age FROM users ORDER BY age DESC")
    or die "准备查询失败: " . $DBI::errstr;
$sth->execute() or die "执行查询失败: " . $DBI::errstr;

print "\n--- 查询结果 ---\n";
while (my $row = $sth->fetchrow_hashref) {
    printf "ID: %d | 姓名: %s | 年龄: %d\n", $row->{id}, $row->{name}, $row->{age};
}

$sth->finish;
$dbh->disconnect;

运行:perl demo.pl,输出连接成功并显示数据。


四、推荐使用异常处理和 UTF-8 支持

使用 RaiseError => 1 启用异常抛出,便于错误处理。添加 sqlite_unicode => 1 支持中文。

use Try::Tiny;  # cpanm Try::Tiny

try {
    my $dbh = DBI->connect($dsn, '', '', { RaiseError => 1, sqlite_unicode => 1 });
    # ... 操作 ...
} catch {
    warn "数据库错误: $_";
};

五、封装 CRUD 操作(UserDAO 模块)

创建一个简单的 DAO 模块(保存为 UserDAO.pm):

package UserDAO;
use strict;
use warnings;
use DBI;
use Exporter 'import';
our @EXPORT_OK = qw(insert delete update find find_all);

my $db_file = 'users.db';
my $dsn = "DBI:SQLite:dbname=$db_file";

sub get_dbh {
    return DBI->connect($dsn, '', '', {
        AutoCommit => 1,
        RaiseError => 1,
        sqlite_unicode => 1
    });
}

sub create_table {
    my $dbh = get_dbh();
    $dbh->do(q{
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            age INTEGER NOT NULL
        )
    });
    $dbh->disconnect;
}

# 增
sub insert {
    my ($name, $age) = @_;
    my $dbh = get_dbh();
    my $sth = $dbh->prepare("INSERT INTO users (name, age) VALUES (?, ?)");
    $sth->execute($name, $age);
    my $id = $dbh->last_insert_id(undef, undef, 'users', undef);
    $sth->finish;
    $dbh->disconnect;
    return $id;
}

# 删
sub delete {
    my ($id) = @_;
    my $dbh = get_dbh();
    my $sth = $dbh->prepare("DELETE FROM users WHERE id = ?");
    my $rows = $sth->execute($id);
    $sth->finish;
    $dbh->disconnect;
    return $rows;
}

# 改
sub update {
    my ($id, $name, $age) = @_;
    my $dbh = get_dbh();
    my $sth = $dbh->prepare("UPDATE users SET name = ?, age = ? WHERE id = ?");
    my $rows = $sth->execute($name, $age, $id);
    $sth->finish;
    $dbh->disconnect;
    return $rows;
}

# 查单个
sub find {
    my ($id) = @_;
    my $dbh = get_dbh();
    my $sth = $dbh->prepare("SELECT * FROM users WHERE id = ?");
    $sth->execute($id);
    my $row = $sth->fetchrow_hashref;
    $sth->finish;
    $dbh->disconnect;
    return $row;
}

# 查全部
sub find_all {
    my $dbh = get_dbh();
    my $sth = $dbh->prepare("SELECT * FROM users ORDER BY id DESC");
    $sth->execute();
    my @users;
    while (my $row = $sth->fetchrow_hashref) {
        push @users, $row;
    }
    $sth->finish;
    $dbh->disconnect;
    return \@users;
}

# 初始化
create_table();

1;

使用示例(demo_dao.pl):

#!/usr/bin/perl
use strict;
use warnings;
use UserDAO qw(insert find_all);

my $id = insert('王五', 22);
print "插入 ID: $id\n";

my $users = find_all();
print "\n--- 所有用户 ---\n";
foreach my $user (@$users) {
    print "ID: $user->{id}, 姓名: $user->{name}, 年龄: $user->{age}\n";
}

运行:perl demo_dao.pl


六、事务支持(Transaction)

SQLite 支持事务,确保数据一致性。

#!/usr/bin/perl
use strict;
use warnings;
use DBI;

my $dbh = DBI->connect("DBI:SQLite:dbname=accounts.db", '', '', { RaiseError => 1 });
$dbh->do("CREATE TABLE IF NOT EXISTS accounts (id INTEGER PRIMARY KEY, balance INTEGER)");
$dbh->{AutoCommit} = 0;  # 开启事务模式

sub transfer {
    my ($from_id, $to_id, $amount) = @_;
    eval {
        my $sth1 = $dbh->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
        $sth1->execute($amount, $from_id);

        my $sth2 = $dbh->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
        $sth2->execute($amount, $to_id);

        $dbh->commit;  # 提交
        print "转账成功!\n";
    };
    if ($@) {
        $dbh->rollback;  # 回滚
        warn "转账失败,已回滚: $@";
    }
    $dbh->{AutoCommit} = 1;
    $dbh->disconnect;
}

# 测试(先插入测试数据)
$dbh->{AutoCommit} = 1;
$dbh->do("INSERT OR IGNORE INTO accounts (id, balance) VALUES (1, 1000), (2, 0)");
$dbh->{AutoCommit} = 0;

transfer(1, 2, 100);

七、常见问题与最佳实践

问题解决方案
中文乱码使用 sqlite_unicode => 1;确保 Perl 脚本保存为 UTF-8
数据库文件路径使用绝对路径:use Cwd; my $dsn = "DBI:SQLite:dbname=" . Cwd::abs_path("data.db");
多线程安全SQLite 适合读多写少;高并发用 WAL 模式:$dbh->do("PRAGMA journal_mode = WAL;");
性能优化添加索引:$dbh->do("CREATE INDEX IF NOT EXISTS idx_name ON users(name);");;批量操作用事务
# 优化示例
$dbh->do("PRAGMA journal_mode = WAL;");
$dbh->do("PRAGMA synchronous = NORMAL;");

八、推荐工具

  • DB Browser for SQLite:图形化管理工具(类似 Perl DBI 的可视化)
  • 下载:https://sqlitebrowser.org/
  • DBI::Shelldbish:Perl 交互式 SQL 工具
  • 安装:cpanm DBI::Shell
  • 使用:dbish dbi:SQLite:users.db
  • VS Code / Padre:Perl IDE,支持 DBI 插件

九、完整项目结构示例

project/
├── demo.pl             ← 主入口
├── UserDAO.pm          ← DAO 模块
├── demo_dao.pl         ← 测试文件
└── users.db            ← 自动生成

demo.pl 中引入并使用 DAO 模块。


总结:SQLite + Perl 组合非常适合脚本和轻量级应用开发,代码简洁、依赖少、无需额外服务器。

立即复制代码运行,你将拥有一个完整的 SQLite 数据库管理系统!

如需 Mojolicious + SQLite高级事务示例性能调优,欢迎继续提问!

文章已创建 2326

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部