下面是一份 完整的 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”。
三、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::Shell 或 dbish: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、高级事务示例 或 性能调优,欢迎继续提问!