许多WEB应用程序内部通常重复运行带不同自变量的相同数据库查询,或以全有或全无块的形式执行一组相关查询。要满足这些要求,大多数数据库系统(包括Mysql)支持预编译查询与事务,多数脚本语言(如PHP和Perl)也拥有内置函数访问这些数据库特性。然而,上述两项特性是Mysql的新功能,因此给那些以前没有见过它们的开发者制造了一些麻烦。
本文旨在解决这一问题。文章讨论了支持MySQL事务和预编译查询的Perl DBI函数,并对其工作原理和应用方法进行说明。
预编译查询
在数据库中执行批量上传时,我们经常见到这样的SQL查询,这些查询仅在提交给INSERT命令的参数上有所不同。在这些情况下,应用所谓的预编译查询是一种常用的优化方法,它为查询建立一个模板,然后再向模板中导入不同的必要值,从而减少了数据库消耗。如果使用得当,这个特性能够显著提高应用程序的性能。
为说明这一点,我们以一个二域表格为例,如下面的列表A所示:
列表A
Mysql> SELECT * FROM users;
+-------+--------+
| fname | lname|
+----------------+
| Joe| Blow|
+-------+--------+
1 row in set (0.09 sec)
现在,假设我需要通过INSERT查询向这个表格中输入一组新记录。很明显,每次运行时,查询的格式保持不变,只有输入的值发生变化。要完成这一操作,最佳方法是为INSERT查询建立一个内置DBI“占位符”的模板,然后在每次运行时用实际值来代替占位符。如列表B所示:
列表B
#!/usr/bin/perl
use DBI;
# create database connection
my $dbh = DBI->connect("DBI:Mysql:database=somedb;host=localhost", "user", "pass", {'RaiseError' => 1});
# prepare template query
my $sth = $dbh->prepare("INSERT INTO users (fname, lname) VALUES (?, ?)");
# execute query with first set of parameters
$sth->execute('John', 'Doe');
# execute query with second set of parameters
$sth->execute('Jane', 'Low');
# close connection
$dbh->disconnect();
建立并执行一个带Perl DBI预编译SQL查询共分四个简单的步骤:
从一个外部文件中批量插入数据,是上述查询的典型应用。这时,首先调用prepare()方法,然后应用一个循环从文件中读入数据,每运行一次循环,即调用execute()方法在数据库中插入一组值。
事务
事务支持是Mysql的另外一项重要的新特性。简单来说,事务就是一个以全有或全无方式执行的SQL语句块(因为这些语句彼此相互依赖)。事务中的所有语句必须全部成功执行,事务才能成功完成;如果有任何一个语句出现错误,系统就会“退回”到原始状态,以避免数据连接/破坏问题。
在两个银行账户间转账就是一个典型的例子。在数据库中,转账过程包括二个步骤:首先,从源账户余额中提取转账金额,然后将其存入目标账户的余额中。如果第二步发生错误,那么第一步必须倒退到一个前面的“快照”,以避免余额失衡。大部分数据库(包括Mysql)通过一组命令完成这种转账过程。