Perl 原定 E03:SQLite 事务和绑定参数要一起验证
DBI 把连接、预处理、绑定参数和事务边界分成不同层。DBI->connect('dbi:SQLite:dbname=:memory:', ...) 得到数据库句柄;begin_work 关闭自动提交直到 commit 或 rollback;? 占位符由驱动绑定值,不把字符串拼进 SQL。只证明 SELECT 1 能跑,不足以覆盖课程里的工程用法。
累计实验 examples/perl-language/experiments/course-sqlite.pl 创建内存表 events(level, message)。第一段事务插入 INFO/kept 后 commit,第二段插入 ERROR/rollback 后 rollback;最后 SELECT COUNT(*) 只剩一行,按绑定参数查询 level = ? 返回 kept。t/course-dependencies.t 同样断言回滚行消失、参数化查询返回预期计数。
1 | |
这段合成输入含单引号、空格、OR 1=1 和 SQL 注释前缀。TAP 断言 sqlite.bound_payload=1,并且总行数从提交后的 1 变成 2,而不是被条件扩展成所有行;这证明它作为一个值进入表中。实验结尾显式 disconnect,把“事务结束”与“连接释放”分开。
反例是字符串拼接:"... WHERE message = '$payload'" 会把输入内容和 SQL 语法混在一起,既难处理引号,也可能把恶意片段当成语法执行。本课程的实验没有连接外部数据库,也没有声明并发隔离级别或 WAL 行为;它只证明 DBI 1.655、DBD::SQLite 1.78、SQLite engine 3.51.1 在本 Perl 前缀下可加载,事务提交/回滚和绑定参数路径可复跑。
来源固定在 DBI 1.655 POD、DBD::SQLite 1.78 POD 和源码包 https://cpan.metacpan.org/authors/id/I/IS/ISHIGAKI/DBD-SQLite-1.78.tar.gz。构建日志显示本次编译了发行包中的 sqlite3.c,并安装了 auto/share/dist/DBD-SQLite/sqlite3.c、sqlite3.h、sqlite3ext.h。练习:rollback 之后还能用同一个 $dbh 查询吗?答案是可以,回滚结束的是当前事务,不是销毁连接;放弃连接才调用 disconnect 或让句柄离开作用域。









