☰ Mục lục series
Tài liệu Go tiếng Việt
  1. Bắt đầu (Getting started)
    1. Tổng quan
    2. Tải về và cài đặt
    3. Bắt đầu với Go
    4. Quản lý các bản cài đặt Go
    5. Plugin trình soạn thảo và IDE
  2. Dạo quanh Go (A Tour of Go)
    1. Chào mừng
    2. Package, biến và hàm
    3. Điều khiển luồng
    4. Struct, slice và map
    5. Method và interface
    6. Generics
    7. Xử lý đồng thời
  3. Hướng dẫn (Tutorials)
    1. Danh sách hướng dẫn
    2. Tạo một Go module
    3. Gọi mã của bạn từ một module khác
    4. Trả về và xử lý lỗi
    5. Trả về lời chào ngẫu nhiên
    6. Trả về lời chào cho nhiều người
    7. Thêm một test
    8. Biên dịch và cài đặt ứng dụng
    9. Kết luận
    10. Bắt đầu với workspace nhiều module
    11. Phát triển RESTful API với Go và Gin
    12. Truy cập cơ sở dữ liệu quan hệ
    13. Bắt đầu với generics
    14. Bắt đầu với fuzzing
    15. Làm việc với JSON
    16. Tìm và sửa các dependency có lỗ hổng với govulncheck
    17. Tìm và khắc phục phụ thuộc có lỗ hổng với VS Code Go
    18. Viết ứng dụng web
  4. Viết code Go
    1. Cách viết mã Go
    2. Effective Go
    3. Doc Comment trong Go
  5. Module
    1. Phát triển và publish module
    2. Quản lý phụ thuộc
    3. Tổ chức một module Go
    4. Quản lý mã nguồn của module
    5. Cách đánh số phiên bản module
    6. Quy trình phát hành và đánh phiên bản module
    7. Publish một module
    8. Phát triển một bản cập nhật major version
    9. Tham chiếu tệp go.mod
    10. Ngừng hỗ trợ 'go get' cho việc cài đặt tệp thực thi
  6. Cơ sở dữ liệu (Database)
    1. Truy cập cơ sở dữ liệu quan hệ
    2. Mở một handle cơ sở dữ liệu
    3. Thực thi câu lệnh SQL không trả về dữ liệu
    4. Truy vấn dữ liệu
    5. Dùng prepared statement
    6. Thực thi transaction
    7. Huỷ các thao tác đang chạy
    8. Quản lý kết nối
    9. Tránh rủi ro SQL injection
  7. Chẩn đoán và hiệu năng
    1. Chẩn đoán
    2. Hướng dẫn về Go Garbage Collector
    3. Tối ưu hoá dựa trên profile
    4. Data Race Detector
    5. Gỡ lỗi mã Go bằng GDB
    6. Hỗ trợ coverage profiling cho integration test
  8. Bảo mật (Security)
    1. Tổng quan bảo mật
    2. Thực hành tốt về bảo mật cho lập trình viên Go
    3. Quản lý lỗ hổng trong Go
    4. Cơ sở dữ liệu lỗ hổng của Go
    5. Quét lỗ hổng trong IDE
    6. Chính sách CNA của Go
    7. Go Fuzzing
    8. Chi tiết kỹ thuật của Go Fuzzing
    9. Chính sách bảo mật của Go
    10. Threat Model của Go
    11. Các quyết định về bảo mật của Go
    12. Tuân thủ FIPS 140-3
  9. Công cụ và toolchain
    1. Tài liệu về các lệnh
    2. Về lệnh go
    3. Go Toolchains
    4. Telemetry của Go
    5. Cài đặt Go từ mã nguồn
    6. Cài đặt và sử dụng gccgo
  10. Tham khảo
    1. Câu hỏi thường gặp (FAQ)
    2. Go 1 và tương lai của các chương trình Go
    3. Hướng dẫn chuyển đổi sang encoding/json/v2
    4. Hướng dẫn đóng góp
    5. Đóng góp cho frontend gccgo
  11. Phụ lục
    1. Bảng thuật ngữ
Cơ sở dữ liệu (Database)

Dùng prepared statement

Bản dịch từ go.dev/doc/database/prepared-statements

Bạn có thể định nghĩa một prepared statement để dùng lại nhiều lần. Điều này giúp mã của bạn chạy nhanh hơn một chút nhờ tránh được chi phí tạo lại câu lệnh mỗi lần mã thực hiện thao tác cơ sở dữ liệu.

Lưu ý: Ký hiệu chỗ dành cho tham số trong prepared statement khác nhau tuỳ theo DBMS và driver bạn đang dùng. Ví dụ, driver pq cho Postgres yêu cầu ký hiệu placeholder kiểu $1 thay vì ?.

Prepared statement là gì?

Prepared statement là câu SQL đã được DBMS phân tích cú pháp và lưu lại, thường chứa các placeholder nhưng chưa có giá trị tham số thực tế. Về sau, câu lệnh có thể được thực thi với một bộ giá trị tham số.

Cách dùng prepared statement

Khi bạn dự kiến sẽ thực thi cùng một câu SQL nhiều lần, bạn có thể dùng một sql.Stmt để chuẩn bị trước câu lệnh SQL, rồi thực thi nó khi cần.

Ví dụ dưới đây tạo một prepared statement chọn ra một album cụ thể từ cơ sở dữ liệu. DB.Prepare trả về một sql.Stmt đại diện cho một prepared statement ứng với một đoạn văn bản SQL cho trước. Bạn có thể truyền các tham số của câu lệnh SQL vào Stmt.Exec, Stmt.QueryRow, hoặc Stmt.Query để chạy câu lệnh đó.

// AlbumByID retrieves the specified album.
func AlbumByID(id int) (Album, error) {
	// Define a prepared statement. You'd typically define the statement
	// elsewhere and save it for use in functions such as this one.
	stmt, err := db.Prepare("SELECT * FROM album WHERE id = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	var album Album

	// Execute the prepared statement, passing in an id value for the
	// parameter whose placeholder is ?
	err := stmt.QueryRow(id).Scan(&album.ID, &album.Title, &album.Artist, &album.Price, &album.Quantity)
	if err != nil {
		if err == sql.ErrNoRows {
			// Handle the case of no rows returned.
		}
		return album, err
	}
	return album, nil
}

Hành vi của prepared statement

Một sql.Stmt đã được chuẩn bị cung cấp các method quen thuộc Exec, QueryRow, và Query để gọi câu lệnh. Tìm hiểu thêm về cách dùng các method này tại Truy vấn dữ liệu và Thực thi câu lệnh SQL không trả về dữ liệu.

Tuy nhiên, vì một sql.Stmt vốn đã đại diện cho một câu lệnh SQL định sẵn, nên các method Exec, QueryRow, và Query của nó chỉ nhận các giá trị tham số SQL tương ứng với các placeholder, mà bỏ qua phần văn bản SQL.

Bạn có thể định nghĩa một sql.Stmt mới theo nhiều cách khác nhau, tuỳ theo bạn sẽ dùng nó ra sao.

  • DB.Prepare và DB.PrepareContext tạo một prepared statement có thể được thực thi độc lập, tự nó và nằm ngoài transaction, giống như cách DB.Exec và DB.Query hoạt động.
  • Tx.Prepare, Tx.PrepareContext, Tx.Stmt, và Tx.StmtContext tạo một prepared statement để dùng trong một transaction cụ thể. Prepare và PrepareContext dùng văn bản SQL để định nghĩa câu lệnh. Stmt và StmtContext dùng kết quả của DB.Prepare hoặc DB.PrepareContext. Nghĩa là, chúng chuyển một sql.Stmt không dành cho transaction thành một sql.Stmt dành cho chính transaction này.
  • Conn.PrepareContext tạo một prepared statement từ một sql.Conn, vốn đại diện cho một kết nối được giữ riêng.

Hãy bảo đảm stmt.Close được gọi khi mã của bạn đã dùng xong một câu lệnh. Việc này sẽ giải phóng mọi tài nguyên cơ sở dữ liệu (chẳng hạn các kết nối bên dưới) có thể đang gắn với nó. Với những câu lệnh chỉ là biến cục bộ trong một hàm, chỉ cần defer stmt.Close() là đủ.

Các hàm để tạo prepared statement

Hàm Mô tả
DB.Prepare
DB.PrepareContext
Chuẩn bị một câu lệnh để thực thi độc lập, hoặc để về sau được chuyển thành prepared statement nằm trong transaction bằng Tx.Stmt.
Tx.Prepare
Tx.PrepareContext
Tx.Stmt
Tx.StmtContext
Chuẩn bị một câu lệnh để dùng trong một transaction cụ thể. Tìm hiểu thêm tại Thực thi transaction.
Conn.PrepareContext Dùng với các kết nối được giữ riêng. Tìm hiểu thêm tại Quản lý kết nối.

Nội dung gốc: Go Documentation © The Go Authors, giấy phép CC BY 3.0. Bản dịch và ghi chú: Lê Văn Dũng.