DBI 採用面向對象風格:DBI->connect() 返回 $dbh(Database Handle),$dbh->prepare() 返回 $sth(Statement Handle)。所有操作通過句柄調用方法完成。
| 符號 | 含義 |
|---|---|
$dbh | 數據庫連接句柄 |
$sth | 語句/查詢句柄 |
$fh | 文件句柄 |
$h | 通用句柄 |
$rc | 布爾返回碼 |
$rv | 整數返回值 |
$rows | 影響行數 |
@ary | 行數組 |
#!/usr/bin/perl
use DBI;
use strict;
my $dsn = "DBI:mysql:database=sampdb;host=localhost";
my $user = "sampadm";
my $pass = "secret";
my $dbh = DBI->connect($dsn, $user, $pass, { RaiseError => 1 });
my $sth = $dbh->prepare(q{
SELECT last_name, first_name, suffix, email,
street, city, state, zip, phone
FROM member ORDER BY last_name
});
$sth->execute();
while (my @row = $sth->fetchrow_array()) {
print join("\t", @row), "\n";
}
$sth->finish();
$dbh->disconnect();
| 模式 | 屬性設置 | 行為 | 適用場景 |
|---|---|---|---|
| 自動異常 | RaiseError=>1 | 出錯自動 die,附帶錯誤信息 | 多數腳本,簡化代碼 |
| 警告繼續 | PrintError=>1(默認) | warn 但不退出 | 交互式、非關鍵路徑 |
| 手動檢查 | RaiseError=>0, PrintError=>0 | 需檢查 $DBI::err/errstr | 需自定義錯誤提示、Web 應用 |
# 手動檢查模式範例
my $dbh = DBI->connect($dsn, $user, $pass, { RaiseError=>0, PrintError=>0 })
or die "Connect failed: $DBI::errstr";
my $sth = $dbh->prepare($sql) or die $dbh->errstr;
$sth->execute() or die $sth->errstr;
do($sql) = prepare() + execute(),返回影響行數(0E0 表示 0 行但成功)。defined($rows) 而非 $rows(因 0E0 為真)。my $rows = $dbh->do("INSERT INTO t (c) VALUES (?)", undef, $val);
die $dbh->errstr unless defined $rows;
printf "影響 %d 行\n", $rows;
| 方法 | 返回值 | 特點 |
|---|---|---|
fetchrow_array() | 列值數組 | 最常用,支持列表賦值 my ($a,$b)=$sth->fetchrow_array |
fetchrow_arrayref() | 數組引用 | 高效,但需注意引用複用問題 |
fetch() | 同 fetchrow_arrayref | 別名 |
fetchrow_hashref() | 哈希引用 {col=>val} | 按列名訪問,大小寫敏感,性能稍低 |
# 強制小寫鍵
$sth->{FetchHashKeyName} = 'NAME_lc';
# 或
my $row = $sth->fetchrow_hashref('NAME_lc');
# 單行單列
my $count = $dbh->selectrow_array("SELECT COUNT(*) FROM member");
# 單行多列
my ($name, $email) = $dbh->selectrow_array("SELECT name, email FROM member WHERE id=1");
# LIMIT 1 場景
my ($pres, $dob) = $dbh->selectrow_array(
"SELECT name, birth FROM president ORDER BY birth DESC LIMIT 1");
# 返回矩陣引用 [ [row1], [row2], ... ]
my $matrix = $dbh->selectall_arrayref("SELECT * FROM member");
# 訪問第 i 行第 j 列:$matrix->[$i][$j]
# 也可先 prepare 再 fetchall
$sth = $dbh->prepare($sql);
$sth->execute();
my $matrix = $sth->fetchall_arrayref();
my $val = $row[0]; # 來自數據庫的 NULL 變為 Perl undef
# 錯誤寫法
if (!$val) ... # 0、''、undef 同樣為假
if ($val eq '') ... # undef eq '' 為真
# 正確寫法
if (!defined $val) { ... } # 是 NULL
elsif ($val eq '') { ... } # 空字符串
elsif ($val == 0) { ... } # 數值 0
else { ... } # 其他
my $sql = qq{INSERT INTO member (last, first) VALUES (?, ?)};
$dbh->do($sql, undef, $last, $first); # 佔位符自動處理引用、轉義
prepare,避免重複解析quote() 防注入$sth->execute();
$sth->bind_col(1, \my $last);
$sth->bind_col(2, \my $first);
while ($sth->fetch()) {
print "$last, $first\n"; # 直接使用變量
}
# 或批量綁定
$sth->bind_columns(\my ($last, $first, $email));
# 從 ~/.my.cnf [client] 讀取
my $dsn = "DBI:mysql:;mysql_read_default_file=$ENV{HOME}/.my.cnf";
# 指定組 [dbi]
my $dsn = "DBI:mysql:;mysql_read_default_group=dbi";
# 腳本內參數優先級高於配置文件
# 代碼控制
DBI->trace(2, 'dbi_trace.log'); # 全局級別 2
$sth->trace(2, 'stmt_trace.log'); # 單句柄
# 環境變量控制(影響所有腳本)
export DBI_TRACE=2=trace.log # bash
setenv DBI_TRACE 2=trace.log # csh
# 關閉
export DBI_TRACE=0
$sth->{NAME}:列名數組引用$sth->{NUM_OF_FIELDS}:列數$sth->{mysql_max_length}:各列最大顯示寬度$sth->{mysql_type_name}:列類型名可構建通用表格輸出、動態報表、Schema 比對等工具。
Perl DBI 通過統一的句柄體系、靈活的錯誤模式、佔位符與綁定機制、豐富的元數據接口,提供了工業級的數據庫交互能力。掌握核心 API 與最佳實踐,能顯著提升腳本的健壯性、安全性與可維護性。