# Ubuntu/Debian
sudo apt-get install libdbi-perl libdbd-mysql-perl mysql-client
# CentOS/RHEL
sudo yum install perl-DBI perl-DBD-MySQL mysql
# CPAN 手動安裝
cpan DBI DBD::mysql
mysql_demo.pl#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use feature 'say';
# ========== 配置 ==========
my $dsn = "DBI:mysql:database=testdb;host=127.0.0.1;port=3306;mysql_enable_utf8=1";
my $user = "perl_user";
my $pass = "PerlPass123!";
# ============================
# 1. 建立連接(RaiseError 自動拋出異常,AutoCommit 開啟)
my $dbh = DBI->connect($dsn, $user, $pass, {
RaiseError => 1,
PrintError => 0,
AutoCommit => 1,
mysql_auto_reconnect => 1,
}) or die "連接失敗: $DBI::errstr";
say "MySQL 連接成功,Server 版本: ", $dbh->{mysql_serverversion};
# 2. 創建測試表
$dbh->do(q{
CREATE TABLE IF NOT EXISTS perl_test (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
});
# 3. 插入數據(預處理語句,防注入、提升性能)
my $sth_ins = $dbh->prepare("INSERT INTO perl_test (name, email) VALUES (?, ?)");
$sth_ins->execute('Alice', 'alice@example.com');
$sth_ins->execute('Bob', 'bob@example.com');
$sth_ins->execute('Charlie', undef); # NULL 值
say "插入 3 行,最後自增 ID: ", $dbh->{mysql_insertid};
# 4. 批量插入(execute_array)
my $data = [
['David', 'david@example.com'],
['Eve', 'eve@example.com'],
['Frank', 'frank@example.com'],
];
my $tuples = $sth_ins->execute_array({ArrayTupleStatus => \my @status}, $data);
say "批量插入 $tuples 行";
# 5. 查詢數據
my $sth_sel = $dbh->prepare("SELECT id, name, email, created_at FROM perl_test WHERE name LIKE ?");
$sth_sel->execute('%a%'); # 包含 a 的名字
say "\n查詢結果 (name LIKE '%a%'):";
while (my $row = $sth_sel->fetchrow_hashref) {
printf "ID: %-3d Name: %-10s Email: %-25s Created: %s\n",
$row->{id}, $row->{name}, $row->{email} // 'NULL', $row->{created_at};
}
# 6. 更新數據
my $sth_upd = $dbh->prepare("UPDATE perl_test SET email = ? WHERE name = ?");
my $rows = $sth_upd->execute('alice.new@example.com', 'Alice');
say "\n更新 $rows 行";
# 7. 刪除數據
my $sth_del = $dbh->prepare("DELETE FROM perl_test WHERE name = ?");
$rows = $sth_del->execute('Charlie');
say "刪除 $rows 行";
# 8. 事務控制示例
eval {
$dbh->begin_work;
$dbh->do("INSERT INTO perl_test (name) VALUES ('Txn_Test')");
$dbh->do("UPDATE perl_test SET name = 'Txn_Test_2' WHERE name = 'Txn_Test'");
$dbh->commit;
say "事務提交成功";
};
if ($@) {
$dbh->rollback;
warn "事務回滾: $@";
}
# 9. 斷開連接
$dbh->disconnect;
say "\n連接已關閉,腳本結束。";
prepare/execute):防 SQL 注入、計劃複用、類型安全。RaiseError => 1:異常自動 die,配合 eval 捕獲,避免靜默失敗。mysql_enable_utf8=1(DBD::mysql < 4.041)或 mysql_enable_utf8mb4=1(新版),確保 UTF-8 全鏈路正確。DBIx::Connector 或 Mojo::mysql 管理連接池,避免頻繁連接/斷開開銷。eval { ... }; if ($@) { rollback; log; } 覆蓋所有寫操作。$sth->execute; while (my $row = $sth->fetchrow_hashref) { ... } 避免一次性載入內存。| 現象 | 原因 | 解決 |
|---|---|---|
install_driver(mysql) failed | 缺少 DBD::mysql 或客戶端庫 | 安裝系統包或 cpan DBD::mysql |
| 中文亂碼 / 顯示 | 字符集協商失敗 | DSN 加 mysql_enable_utf8mb4=1,表/庫 CHARSET=utf8mb4,連接後 $dbh->do("SET NAMES utf8mb4") |
MySQL server has gone away | 連接超時/斷開 | 啟用 mysql_auto_reconnect=1,或用連接池心跳檢測 |
預處理佔位符 ? 不工作 | 在識別符位置(表名、列名)不能用佔位符 | 表名/列名用 QUOTENAME 或應用層驗證後拼接 |
Perl + DBI 是系統運維、數據遷移、ETL 腳本的經典利器。掌握預處理、事務、UTF-8、連接池四大核心,即可編寫健壯、高性能的 MySQL 自動化腳本。