====== Go Stdlib Wiki: package database/sql ======
===== 1. Overview =====
database/sql provides a generic SQL database interface in Go. It does NOT talk to a database by itself. Instead, it works together with a database-specific driver (e.g., lib/pq for PostgreSQL, go-sql-driver/mysql for MySQL) that implements the low-level protocol.
generic /dʒəˈnerɪk/ = chung, tổng quát
driver /ˈdraɪvər/ = trình điều khiển (thư viện kết nối DB)
protocol /ˈproʊtəˌkɔːl/ = giao thức
import "database/sql"
===== 2. What it is for =====
Use database/sql to:
Open/manage database connections via a driver
Run SQL queries (Query, QueryRow) and commands (Exec)
Use prepared statements (Prepare)
Control transactions (Begin, Commit, Rollback)
Configure connection pooling (max open/idle, lifetime)
transaction /trænˈzækʃən/ = giao dịch
prepared statement /prɪˈperd ˈsteɪtmənt/ = câu lệnh chuẩn bị sẵn
connection pool /kəˈnekʃən puːl/ = bể kết nối (tái sử dụng kết nối)
===== 3. What it is NOT for =====
It does NOT provide an ORM (like GORM).
It does NOT include DB drivers.
It does NOT auto-migrate schemas.
If you need higher-level features, you use libraries on top of it.
ORM /ˌɔːrˈɛm/ = Object-Relational Mapping (ánh xạ object–bảng)
===== 4. Core types (what is what) =====
==== 4.1 *sql.DB ====
What it is: a handle representing a pool of connections, safe for concurrent use.
Important: sql.Open does not necessarily connect immediately; use Ping() to verify.
concurrent /kənˈkɝːənt/ = đồng thời
handle /ˈhændl/ = “tay cầm”/đối tượng đại diện
==== 4.2 *sql.Rows / *sql.Row ====
Rows for multiple-row results (Query)
Row for single-row results (QueryRow)
==== 4.3 sql.Result ====
Returned from Exec, used to get:
LastInsertId() (if supported by driver)
RowsAffected()
==== 4.4 *sql.Tx ====
Transaction handle created by Begin/BeginTx.
==== 4.5 *sql.Stmt ====
Prepared statement created by Prepare (or db.PrepareContext).
===== 5. Driver relationship (why you need pq etc.) =====
database/sql defines the common API. Drivers register themselves (via database/sql/driver) so database/sql can call them.
Typical usage pattern:
Import driver for its side effects (registration)
Use sql.Open(driverName, dsn)
Example (PostgreSQL driver github.com/lib/pq):
import (
"database/sql"
_ "github.com/lib/pq"
)
db, err := sql.Open("postgres", "postgres://user:pass@localhost:5432/dbname?sslmode=disable")
side effect /saɪd ɪˈfekt/ = tác dụng phụ (ở đây: tự đăng ký driver khi import)
DSN /ˌdiː es ˈɛn/ = Data Source Name (chuỗi cấu hình kết nối)
===== 6. Common recipes =====
==== 6.1 Open and verify connection ====
db, err := sql.Open("postgres", dsn)
if err != nil {
return err
}
defer db.Close()
if err := db.Ping(); err != nil {
return err
}
==== 6.2 Query multiple rows ====
rows, err := db.Query("SELECT id, name FROM users WHERE active = $1", true)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var id int64
var name string
if err := rows.Scan(&id, &name); err != nil {
return err
}
}
if err := rows.Err(); err != nil {
return err
}
scan /skæn/ = quét/đổ dữ liệu từ row vào biến
==== 6.3 Query a single row ====
var count int
err := db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count)
==== 6.4 Exec (INSERT/UPDATE/DELETE) ====
res, err := db.Exec("UPDATE users SET active = $1 WHERE id = $2", true, 10)
if err != nil {
return err
}
n, _ := res.RowsAffected()
_ = n
==== 6.5 Transaction (Tx) ====
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback() // safe: no-op if committed
if _, err := tx.Exec("UPDATE accounts SET balance = balance - $1 WHERE id = $2", 100, 1); err != nil {
return err
}
if _, err := tx.Exec("UPDATE accounts SET balance = balance + $1 WHERE id = $2", 100, 2); err != nil {
return err
}
return tx.Commit()
===== 7. Connection pool settings =====
Tuning (depends on workload/DB limits):
db.SetMaxOpenConns(n)
db.SetMaxIdleConns(n)
db.SetConnMaxLifetime(d)
db.SetConnMaxIdleTime(d)
tuning /ˈtuːnɪŋ/ = tinh chỉnh
workload /ˈwɝːkˌloʊd/ = tải công việc
===== 8. Quick “what is what for” map =====
database/sql — standard, generic SQL API
DB driver (e.g., lib/pq) — actual DB protocol implementation
sql.Open — create *sql.DB (pool handle), not necessarily connect yet
db.Ping — verify connectivity
db.Query / db.QueryRow — SELECT
db.Exec — INSERT/UPDATE/DELETE
db.Begin / tx.Commit / tx.Rollback — transactions
db.SetMaxOpenConns etc. — pool configuration