编写查询
设计
Bun 的目标是帮助您编写惯用的 SQL,而不是将其隐藏在笨拙的结构后面。建议您使用数据库的 CLI(例如 psql)开始编写和测试查询,然后使用 Bun 的查询构建器重建生成的查询。
主要功能包括
例如,以下 Go 代码
err := db.NewSelect().
Model(book).
ColumnExpr("lower(name)").
Where("? = ?", bun.Ident("id"), "some-id").
Scan(ctx)
不出所料地生成以下查询
SELECT lower(name)
FROM "books"
WHERE "id" = 'some-id'
Scan 和 Exec
您可以使用 bun.DB, bun.Tx 或 bun.Conn 创建查询
创建查询后,可以使用 Exec
执行它
result, err := db.NewInsert().Model(&user).Exec(ctx)
或者使用 Scan
,它执行相同的操作,但省略 sql.Result
(仅适用于选择)
err := db.NewSelect().Model(&user).Where("id = 1").Scan(ctx)
默认情况下,Exec
将列扫描到模型中,但您也可以指定其他目标
err := db.NewSelect().Model((*User)(nil)).Where("id = 1").Scan(ctx, &user)
您可以扫描到
- 结构体中,
map[string]interface{}
中,- 标量类型中,
- 上述类型的切片中。
// Scan into a map.
m := make(map[string]interface{})
err := db.NewSelect().Model(&user).Where("id = 1").Scan(ctx, &m)
// Scan into a slice of maps.
ms := make([]map[string]interface{}, 0)
err := db.NewSelect().Model(&user).Limit(100).Scan(ctx, &ms)
// Scan into a var.
var name string
err := db.NewSelect().Model(&user).Column("name").Where("id = 1").Scan(ctx, &name)
// Scan columns into separate slices.
var ids []int64
var names []string
err := db.NewSelect().Model(&user).Column("id", "name").Limit(100).Scan(ctx, &ids, &names)
bun.IDB
Bun 提供 bun.IDB
接口,您可以使用它来接受 bun.DB
、bun.Tx
和 bun.Conn
func InsertUser(ctx context.Context, db bun.IDB, user *User) error {
_, err := db.NewInsert().Model(user).Exec(ctx)
return err
}
err := InsertUser(ctx, db, user)
err := db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
return InsertUser(ctx, tx, user)
})
扫描行
要执行自定义查询并扫描所有行
rows, err := db.QueryContext(ctx, "SELECT * FROM users")
if err != nil {
panic(err)
}
err = db.ScanRows(ctx, rows, &users)
要逐行扫描
rows, err := db.NewSelect().Model((*User)(nil)).Rows(ctx)
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
user := new(User)
if err := db.ScanRow(ctx, rows, user); err != nil {
panic(err)
}
}
if err := rows.Err(); err != nil {
panic(err)
}
Scanonly
有时,您希望在插入或更新数据时忽略某些字段,但仍然能够将列扫描到被忽略的字段中。您可以使用 scanonly
选项来实现这一点
type Model struct {
Foo string
- Bar string `"bun:"-"`
+ Bar string `"bun:",scanonly"`
}
忽略未知列
要丢弃未知 SQL 列,可以使用 WithDiscardUnknownColumns
数据库选项
db := bun.NewDB(sqldb, pgdialect.New(), bun.WithDiscardUnknownColumns())
如果您想忽略单个列,只需用下划线将其替换
err := db.NewSelect().
ColumnExpr("1 AS _rank"). // ignore the column when scanning
OrderExpr("_rank DESC"). // but use it for sorting
Scan(ctx)