sqlx

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 8, 2026 License: MIT Imports: 2 Imported by: 0

README

sqlx

sqlx 是一个为 Go 标准库 database/sql 提供一系列扩展的库。 sqlx 版本的 sql.DBsql.TXsql.Stmt 等全部保持底层接口不变, 因此它们的接口是标准库接口的超集。这使得将现有使用 database/sql 的 代码库与 sqlx 集成相对轻松。

主要功能

  • 将行序列化到结构体(支持嵌入结构体)、map 和切片中
  • 命名参数支持(包括预编译语句)
  • GetSelect 快速从查询结果转换到结构体/切片

安装

go get gitee.com/BoYiXiao/sqlx

已知问题

行标题可能产生歧义(SELECT 1 AS a, 2 AS a),并且 Columns() 的结果不会完全限定以下查询中的列名:

SELECT a.id, a.name, b.id, b.name FROM foos AS a JOIN foos AS b ON a.parent = b.id;

这使得结构体或 map 目标变得不明确。请在查询中使用 AS 为列赋予 不同的名称,使用 rows.Scan 手动扫描,或使用 SliceScan 获取结果切片。

用法示例

package main

import (
    "database/sql"
    "fmt"
    "log"
    
    _ "github.com/lib/pq"
    "gitee.com/BoYiXiao/sqlx"
)

var schema = `
CREATE TABLE person (
    first_name text,
    last_name text,
    email text
);

CREATE TABLE place (
    country text,
    city text NULL,
    telcode integer
)`

type Person struct {
    FirstName string `db:"first_name"`
    LastName  string `db:"last_name"`
    Email     string
}

type Place struct {
    Country string
    City    sql.NullString
    TelCode int
}

func main() {
    // 连接数据库(会 Ping 尝试连接)
    // 使用 sqlx.Open() 获得与 sql.Open() 相同的行为
    db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
    if err != nil {
        log.Fatalln(err)
    }

    // 执行 schema;多语句 Exec 行为因数据库驱动而异
    db.MustExec(schema)
    
    tx := db.MustBegin()
    tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "Jason", "Moiron", "jmoiron@jmoiron.net")
    tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "John", "Doe", "johndoeDNE@gmail.net")
    tx.MustExec("INSERT INTO place (country, city, telcode) VALUES ($1, $2, $3)", "United States", "New York", "1")
    tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Hong Kong", "852")
    tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Singapore", "65")
    // 命名查询可使用结构体
    tx.NamedExec("INSERT INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)", &Person{"Jane", "Citizen", "jane.citzen@example.com"})
    tx.Commit()

    // 查询数据库,将结果存储到 []Person 中
    people := []Person{}
    db.Select(&people, "SELECT * FROM person ORDER BY first_name ASC")
    jason, john := people[0], people[1]

    fmt.Printf("%#v\n%#v", jason, john)

    // 也可获取单条结果,类似 QueryRow
    jason = Person{}
    err = db.Get(&jason, "SELECT * FROM person WHERE first_name=$1", "Jason")
    fmt.Printf("%#v\n", jason)

    // 如果有 null 字段并使用 SELECT *,必须在结构体中使用 sql.Null*
    places := []Place{}
    err = db.Select(&places, "SELECT * FROM place ORDER BY telcode ASC")
    if err != nil {
        fmt.Println(err)
        return
    }
    usa, singsing, honkers := places[0], places[1], places[2]
    
    fmt.Printf("%#v\n%#v\n%#v\n", usa, singsing, honkers)

    // 循环遍历行,使用单个结构体
    place := Place{}
    rows, err := db.Queryx("SELECT * FROM place")
    for rows.Next() {
        err := rows.StructScan(&place)
        if err != nil {
            log.Fatalln(err)
        } 
        fmt.Printf("%#v\n", place)
    }

    // 命名查询,使用 `:name` 作为绑定变量。
    _, err = db.NamedExec(`INSERT INTO person (first_name,last_name,email) VALUES (:first,:last,:email)`, 
        map[string]interface{}{
            "first": "Bin",
            "last": "Smuth",
            "email": "bensmith@allblacks.nz",
    })

    rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:fn`, map[string]interface{}{"fn": "Bin"})

    // 命名查询也可使用结构体。
    rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:first_name`, jason)
    
    // 批量插入 - 使用结构体
    personStructs := []Person{
        {FirstName: "Ardie", LastName: "Savea", Email: "asavea@ab.co.nz"},
        {FirstName: "Sonny Bill", LastName: "Williams", Email: "sbw@ab.co.nz"},
        {FirstName: "Ngani", LastName: "Laumape", Email: "nlaumape@ab.co.nz"},
    }

    _, err = db.NamedExec(`INSERT INTO person (first_name, last_name, email)
        VALUES (:first_name, :last_name, :email)`, personStructs)

    // 批量插入 - 使用 map
    personMaps := []map[string]interface{}{
        {"first_name": "Ardie", "last_name": "Savea", "email": "asavea@ab.co.nz"},
        {"first_name": "Sonny Bill", "last_name": "Williams", "email": "sbw@ab.co.nz"},
        {"first_name": "Ngani", "last_name": "Laumape", "email": "nlaumape@ab.co.nz"},
    }

    _, err = db.NamedExec(`INSERT INTO person (first_name, last_name, email)
        VALUES (:first_name, :last_name, :email)`, personMaps)
}

Documentation

Overview

Package sqlx 为 database/sql 提供了通用扩展。

它旨在无缝封装 database/sql,并提供在数据库驱动应用程序开发中 实用的便捷方法。所有底层的 database/sql 方法均保持不变。相反, 所有扩展行为都通过封装类型上定义的新方法实现。

新增的功能包括:结构体扫描、命名查询支持、针对不同驱动的查询重绑定、 常用错误处理的便捷简写等。

DDD 分层架构

本项目采用领域驱动设计(DDD)模式组织代码:

  • core/(领域层):纯接口定义、Row/Rows 核心类型、绑定变量工具、扫描与查询纯函数
  • db/(基础设施层):DB/Tx/Stmt/Conn 具体实现、命名查询支持、Context 感知方法
  • reflectx/:反射扩展工具,提供结构体字段到名称的映射能力
  • types/:SQL 扫描目标类型(JSON、GzippedText、BitBool 等)

所有公开 API 通过根包统一重导出,保证向后兼容性。

Index

Constants

View Source
const (
	UNKNOWN  = core.UNKNOWN
	QUESTION = core.QUESTION
	DOLLAR   = core.DOLLAR
	NAMED    = core.NAMED
	AT       = core.AT
)

-- 绑定变量常量 --

Variables

View Source
var (
	BindType   = core.BindType
	BindDriver = core.BindDriver
	Rebind     = core.Rebind
	RebindBuff = core.RebindBuff
	In         = core.In
)

-- 绑定变量函数 --

View Source
var (
	Select     = core.Select
	Get        = core.Get
	MustExec   = core.MustExec
	StructScan = core.StructScan
	SliceScan  = core.SliceScan
	MapScan    = core.MapScan
	ScanAll    = core.ScanAll
)

-- 扫描与查询函数 --

View Source
var (
	IsScannable       = core.IsScannable
	Mapper            = core.Mapper
	FieldsByTraversal = core.FieldsByTraversal
)

-- 辅助函数 --

View Source
var (
	Connect     = db.Connect
	MustConnect = db.MustConnect
	Open        = db.Open
	MustOpen    = db.MustOpen
	NewDb       = db.NewDb
	Preparex    = db.Preparex
	LoadFile    = db.LoadFile
)

-- 连接与预编译 --

View Source
var (
	Named             = db.Named
	NamedQuery        = db.NamedQuery
	NamedExec         = db.NamedExec
	BindNamed         = db.BindNamed
	BindNamedMapper   = db.BindNamedMapper
	BindStruct        = db.BindStruct
	BindMap           = db.BindMap
	BindArray         = db.BindArray
	CompileNamedQuery = db.CompileNamedQuery
	FixBound          = db.FixBound
)

-- 命名查询 --

View Source
var (
	IsUnsafe  = db.IsUnsafe
	MapperFor = db.MapperFor
)

-- 工具函数 --

View Source
var (
	ConnectContext    = db.ConnectContext
	SelectContext     = db.SelectContext
	GetContext        = db.GetContext
	MustExecContext   = db.MustExecContext
	LoadFileContext   = db.LoadFileContext
	PreparexContext   = db.PreparexContext
	NamedQueryContext = db.NamedQueryContext
	NamedExecContext  = db.NamedExecContext
)

-- Context 函数 --

View Source
var NameMapper = core.NameMapper

-- 名称映射 --

Functions

This section is empty.

Types

type Binder

type Binder = core.Binder

-- 接口 --

type ColScanner

type ColScanner = core.ColScanner

-- 接口 --

type Conn

type Conn = db.Conn

-- 数据库类型 --

type DB

type DB = db.DB

-- 数据库类型 --

type Execer

type Execer = core.Execer

-- 接口 --

type ExecerContext

type ExecerContext = db.ExecerContext

-- Context 接口 --

type Ext

type Ext = core.Ext

-- 接口 --

type ExtContext

type ExtContext = db.ExtContext

-- Context 接口 --

type NamedStmt

type NamedStmt = db.NamedStmt

-- 数据库类型 --

type Preparer

type Preparer = core.Preparer

-- 接口 --

type PreparerContext

type PreparerContext = db.PreparerContext

-- Context 接口 --

type QStmt

type QStmt = db.QStmt

-- 数据库类型 --

type Queryer

type Queryer = core.Queryer

-- 接口 --

type QueryerContext

type QueryerContext = db.QueryerContext

-- Context 接口 --

type Row

type Row = core.Row

-- 核心类型 --

type Rows

type Rows = core.Rows

-- 核心类型 --

type Rowsi

type Rowsi = core.Rowsi

-- 接口 --

type Stmt

type Stmt = db.Stmt

-- 数据库类型 --

type Tx

type Tx = db.Tx

-- 数据库类型 --

Directories

Path Synopsis
Package core 定义了 sqlx 的领域层接口与核心类型。
Package core 定义了 sqlx 的领域层接口与核心类型。
Package db 提供了 sqlx 的基础设施层实现。
Package db 提供了 sqlx 的基础设施层实现。
Package reflectx 实现了对标准 reflect 库的扩展,适用于实现序列化和 反序列化包。
Package reflectx 实现了对标准 reflect 库的扩展,适用于实现序列化和 反序列化包。
Package types 提供了一些实现了 sql.Scanner 和 driver.Valuer 接口的 实用类型,适合用作 database/sql 的扫描和赋值目标。
Package types 提供了一些实现了 sql.Scanner 和 driver.Valuer 接口的 实用类型,适合用作 database/sql 的扫描和赋值目标。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL