sqlx 與 diesel 各自的優點
- 設計理念與使用情境
- diesel
- 以「型別安全的 ORM/Query DSL」為核心。透過 Rust 的型別系統與 DSL(diesel::prelude::*),在編譯時就能檢查欄位與型別的一致性,減少 runtime 錯誤。
- 適合喜歡在程式碼內用 DSL 組 query、並且偏好編譯時期保證的專案。對於標準 CRUD 與關聯操作,diesel 的 DSL 可以讓程式碼更「Rust 化」。
- sqlx
- 原生 async、以 raw SQL 為主的非阻塞 client。你可以直接寫標準 SQL,並能選擇在 build 時以 macro(sqlx::query!)做 SQL 與欄位的編譯時檢查。
- 更適合需要複雜查詢(CTE、視窗函數、原生 SQL 優化)的場景,以及直接在 async handler 內使用資料庫的 web 應用。
- 型別安全與開發流程
- diesel 的優勢:在 compile-time 提供強烈保證,減少 runtime 型別與欄位不一致的錯誤。但在某些複雜查詢或動態 query 時,DSL 可能較難以表達。
- sqlx 的平衡:允許寫 raw SQL 的彈性,同時可啟用 compile-time 檢查(需在 build 時連接到真實 DB 或使用 offline 準備),否則為 runtime 驗證。對於開發流程來說,sqlx 提供較接近 DB 的操作感受。
- 非同步支援與效能考量
- diesel 傳統上是同步 API(有 async 支援方案),在 async web 框架中通常要把工作丟到 blocking thread pool,會增加一些配置與上下文切換成本。
- sqlx 原生支援 tokio/async-std,與 axum、tower 等現代 async 生態整合順暢,避免額外的 blocking 轉換。
- 可維護性與學習成本
- diesel 的 DSL 對習慣完全以型別驅動開發的人友好,但學習曲線與某些查詢的限制值得考量。
- sqlx 更接近 SQL 原生語法,對熟悉 SQL 的開發者更直覺,且在團隊中如果 DB 團隊直接給 SQL,接手更簡單。
為什麼 axum 適合使用 sqlx
- axum 是基於 tokio 的輕量化、模組化 web 框架,handler 通常是 async 函式;axum 的設計鼓勵把共享資源(例如 DB 連線池)注入到 request context(透過 Extension)。
- sqlx 的優勢在於:
- 原生 async 支援:能在 axum handler 內直接 await DB 操作,不需 spawn_blocking,降低複雜度與延遲風險。
- PgPool(或其他 DB pool)可安全跨 handler 分享,並容易注入 axum 的 Extension,實務上常見範例也都採用這種模式。
- 可直接使用 raw SQL:對於需要微調 SQL 或用原生 SQL 做效能優化的 API,sqlx 提供直接控制權。
axum + sqlx 是現代 Rust web 工程常見組合,利於快速開發與效能優化。
在 Windows 與 macOS 安裝 PostgreSQL
以下分別說明 Windows 與 macOS 的安裝方式,包含 GUI 與終端機選項,並提供常見問題的處理方法。
Windows
- 方法 A:Postgres 官方安裝器(EnterpriseDB)
- 下載:到 https://www.postgresql.org/download/windows/ ,點選 EnterpriseDB 連結。
- 執行安裝程式(.exe),安裝步驟通常包含:
- 安裝路徑
- 選擇要安裝的 components(預設包含 server、pgAdmin、StackBuilder)
- 設定 PostgreSQL superuser(postgres)密碼(請記住)
- 選擇 port(預設 5432)
- 選擇 locale
- 完成後會啟動 PostgreSQL 服務(作為 Windows service)。
- 驗證安裝是否成功:
- 在命令提示字元(或 PowerShell)執行:psql -U postgres -h 127.0.0.1 -p 5432
系統會要求輸入密碼,輸入安裝時設定的 postgres 密碼。
- 或開啟 pgAdmin(若安裝)用 GUI 連線。
- 常見問題:
- psql 找不到:將 PostgreSQL 的 bin 路徑(例如 C:\Program Files\PostgreSQL\18\bin)加到 PATH,或使用完整路徑執行 psql.exe。
- Service 無法啟動:檢查 Windows 事件檢視器或 PostgreSQL 的 log(在 data 目錄下)。
- 方法 B:使用 Chocolatey(命令提示字元)
-
安裝 Chocolatey(若尚未安裝):以系統管理員權限在 PowerShell 執行 Chocolatey 官方指令。
-
安裝 PostgreSQL:
choco install postgresql
-
完成後同樣需要確認 service 與 PATH。Chocolatey 會提示安裝位置與初始密碼設定方式。
-
驗證方式同上。
macOS
- 方法 A:Homebrew(推薦給習慣命令列的開發者)
-
安裝 Homebrew(若尚未):在 Terminal 執行官方安裝指令。
-
安裝 PostgreSQL:
brew install postgresql
-
啟動 PostgreSQL:
brew services start postgresql
pg_ctl -D /usr/local/var/postgres start
-
建立初始資料庫(homebrew 安裝後通常會建立 current user 的資料庫):
createdb $(whoami)
-
常見問題:
- 若遇到權限或路徑問題,檢查 Homebrew 的安裝路徑與環境變數。
- 若使用 Apple Silicon(M系列晶片),Homebrew 安裝路徑可能是 /opt/homebrew,注意 PATH 設定。
- 方法 B:Postgres.app(圖形化,一鍵啟動)
- 下載 Postgres.app:https://postgresapp.com/
- 將 Postgres.app 拖到 Applications,啟動之後會在 menu bar 顯示 PostgreSQL 已啟動。
- psql 可透過應用程式內的 shell 或手動將 Postgres.app 的 bin 加到 PATH:
export PATH="/Applications/Postgres.app/Contents/Versions/latest/bin:$PATH"
- 驗證:psql -h 127.0.0.1 -U postgres
- Postgres.app 的好處是簡單易用,適合快速開發環境設定。
基本安全與管理建議
- 初始 superuser(通常是 postgres)請設強密碼,將開發環境的 creds 加入 .env 並加入 .gitignore。
- 若本機只做開發,可允許本機連線(127.0.0.1),但在開發以外環境慎防開放到公共網路。
- 如果需要同時執行多個 PostgreSQL 版本,避免埠號衝突(預設 5432)。
在 Rust 專案用 sqlx 連接 PostgreSQL
提供一個最小可運作的 Rust 範例,程式啟動後嘗試連到 PostgreSQL,並回報「連線成功」或「連線失敗」。不包含任何 CRUD 操作。
前置條件
- 已安裝 Rust
- PostgreSQL 已在本機運作
- 建議在專案目錄放置 .env 存 DATABASE_URL(並加入 .gitignore)
Cargo.toml
請建立一個新的專案
cargo new sqlx_connect_demo
然後在 Cargo.toml 中加入:
[package]
name = "sqlx_connect_demo"
version = "0.1.0"
edition = "2024"
[dependencies]
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "macros"] }
dotenvy = "0.15"
說明:
- runtime-tokio-rustls:使用 tokio runtime 與 rustls,避免系統 openssl 的相依問題。
- postgres:啟用 PostgreSQL 支援。
- macros:若未在 build 時做 compile-time SQL 驗證,也能使用其它 macro 功能。這裡我們主要用 runtime 建立 pool。
- dotenvy:用來從 .env 載入 DATABASE_URL(選用,方便 local 開發)。
.env (放在專案根目錄,切勿推上版本控制)
DATABASE_URL=postgres://myuser:mypassword@127.0.0.1:5432/mydb
調整 myuser、mypassword、host、port、mydb 為你系統上的設定。
main.rs
請把 src/main.rs 改成下列內容:
use sqlx::postgres::PgPoolOptions;
use std::time::Duration;
use dotenvy::dotenv;
use std::env;
use tokio::time;
#[tokio::main]
async fn main() {
dotenv().ok();
let database_url = match env::var("DATABASE_URL") {
Ok(v) => v,
Err(_) => {
eprintln!("錯誤:找不到 DATABASE_URL");
std::process::exit(1);
}
};
// 例如 5 秒超時
let connect_future = PgPoolOptions::new()
.max_connections(5)
.connect(&database_url);
let pool = match time::timeout(Duration::from_secs(5), connect_future).await {
Ok(Ok(p)) => {
println!("成功建立 PgPool");
p
}
Ok(Err(e)) => {
eprintln!("建立 PgPool 失敗: {}", e);
std::process::exit(1);
}
Err(_) => {
eprintln!("建立 PgPool 超時");
std::process::exit(1);
}
};
// ping
match sqlx::query_scalar::<_, i32>("SELECT 1")
.fetch_one(&pool)
.await
{
Ok(v) => println!("Ping 成功(SELECT 1 回傳 {})", v),
Err(e) => {
eprintln!("Ping 失敗: {}", e);
std::process::exit(1);
}
}
}
說明:
- 第一階段在建立 pool 時就可能失敗(例如無法連到 DB、認證錯誤),程式會印錯誤並結束。
- 第二階段透過簡單 query 做 ping,確保連線能成功執行 SQL。
執行
- 在專案根目錄,確認 .env 有設定 DATABASE_URL,然後執行:
cargo run
成功建立 PgPool
Ping 成功(SELECT 1 回傳 1)
建立 PgPool 失敗: error returned from database: password authentication failed for user "myuser"
或
Ping 失敗: error returned from database: connection refused
常見問題與除錯建議
- 找不到 psql / 指令無法執行
- Windows:確認 PostgreSQL 的 bin 路徑加入 PATH,或使用完整路徑執行。
- macOS(Homebrew):確定 /opt/homebrew/bin(Apple Silicon)或 /usr/local/bin 在 PATH。
- 連線被拒(connection refused)
- 檢查 PostgreSQL 服務是否已啟動。
- 確認 host 與 port 是否正確(localhost vs 127.0.0.1),以及防火牆規則。
- 認證錯誤(password authentication failed)
- 確認 DATABASE_URL 中的帳號密碼正確,使用 psql 測試同樣的帳密。
- 權限問題
- 若使用自訂 user,確認該 user 有權限存取指定資料庫(GRANT 或建立時指定)。
- sqlx 連線超時
- 可以調整 connect_timeout 與 pool 設定,或檢查 network/pg_hba.conf 等設定。
- 若在 macOS 用 Postgres.app,記得把 bin 路徑加入 PATH,否則 psql 可能找不到。