Go Wiki:SQLInterface
簡介
database/sql
套件提供一個通用介面,用於 SQL(或類似 SQL)資料庫。有關詳細資訊,請參閱 官方文件。
此頁面提供範例使用模式。
資料庫驅動程式
database/sql
套件必須與資料庫驅動程式搭配使用。請參閱 https://go.dev.org.tw/s/sqldrivers 以取得驅動程式清單。
以下文件假設已匯入驅動程式。
連線到資料庫
Open
用於建立資料庫控制代碼
db, err := sql.Open(driver, dataSourceName)
其中驅動程式指定資料庫驅動程式,而 dataSourceName 指定資料庫特定的連線資訊,例如資料庫名稱和驗證憑證。
請注意,Open
並未直接開啟資料庫連線:這會延遲到執行查詢時。若要在執行查詢前驗證是否可以建立連線,請使用 PingContext
方法
if err := db.PingContext(ctx); err != nil {
log.Fatal(err)
}
使用後,資料庫會使用 Close
關閉。
執行查詢
ExecContext
用於未傳回任何列的查詢
result, err := db.ExecContext(ctx,
"INSERT INTO users (name, age) VALUES ($1, $2)",
"gopher",
27,
)
其中 result 包含最後的插入 ID 和受影響的列數。這些值的可用性取決於資料庫驅動程式。
QueryContext
用於擷取
rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age = $1", age)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name string
if err := rows.Scan(&name); err != nil {
log.Fatal(err)
}
fmt.Printf("%s is %d\n", name, age)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
QueryRowContext
用於僅預期單一列
var age int64
err := db.QueryRowContext(ctx, "SELECT age FROM users WHERE name = $1", name).Scan(&age)
已準備好的陳述式可以使用 PrepareContext
建立
age := 27
stmt, err := db.PrepareContext(ctx, "SELECT name FROM users WHERE age = $1")
if err != nil {
log.Fatal(err)
}
rows, err := stmt.Query(age)
// process rows
ExecContext
、QueryContext
和 QueryRowContext
可以呼叫陳述式。使用後,應使用 Close
關閉陳述式。
交易
交易以 BeginTx
開始
tx, err := db.BeginTx(ctx, nil)
if err != nil {
log.Fatal(err)
}
已涵蓋的 ExecContext
、QueryContext
、QueryRowContext
和 PrepareContext
方法可用於交易中。
處理 NULL
如果資料庫欄位為可為空值,則應將支援空值的其中一種類型傳遞至 Scan。
例如,如果 names 表格中的 name 欄位為可為空值
var name sql.NullString
err := db.QueryRowContext(ctx, "SELECT name FROM names WHERE id = $1", id).Scan(&name)
...
if name.Valid {
// use name.String
} else {
// value is NULL
}
僅 NullByte
、NullBool
、NullFloat64
、NullInt64
、NullInt32
NullInt16
、NullString
和 NullTime
在 database/sql
中實作。特定於資料庫的可為空值類型的實作留給資料庫驅動程式。可支援 NULL
的使用者類型可透過實作介面 database/sql/driver.Valuer
和 database/sql.Scanner
來建立。
您也可以傳遞指標類型。小心效能問題,因為它需要額外的記憶體配置。
var name *string
err := db.QueryRowContext(ctx, "SELECT name FROM names WHERE id = $1", id).Scan(&name)
取得表格
如果您想要從 SQL 查詢中取得結構陣列。
func getTable[T any](rows *sql.Rows) (out []T) {
var table []T
for rows.Next() {
var data T
s := reflect.ValueOf(&data).Elem()
numCols := s.NumField()
columns := make([]interface{}, numCols)
for i := 0; i < numCols; i++ {
field := s.Field(i)
columns[i] = field.Addr().Interface()
}
if err := rows.Scan(columns...); err != nil {
fmt.Println("Case Read Error ", err)
}
table = append(table, data)
}
return table
}
確保處理資料庫中的空值。
type User struct {
UUID sql.NullString
Name sql.NullString
}
rows, err := db.Query("SELECT * FROM Users")
cases := getTable[User](rows)
此內容是 Go Wiki 的一部分。