golang SQL和文档数据格式转换插件库sq的使用

Golang SQL和文档数据格式转换插件库sq的使用

概述

sq是一个命令行工具,提供类似jq风格的访问结构化数据源的能力,包括SQL数据库和CSV/Excel等文档格式。它是sql+jq的结合体。

sq

安装

macOS

brew install sq

Linux

/bin/sh -c "$(curl -fsSL https://sq.io/install.sh)"

Windows

scoop bucket add sq https://github.com/neilotoole/sq
scoop install sq

Go

go install github.com/neilotoole/sq

基本使用

添加数据源

# 下载示例数据库
wget https://sq.io/testdata/sakila.db

# 添加SQLite数据源
sq add ./sakila.db
@sakila  sqlite3  sakila.db

# 列出数据源
sq ls -v
HANDLE   ACTIVE  DRIVER   LOCATION                         OPTIONS
@sakila  active  sqlite3  sqlite3:///Users/demo/sakila.db

查询数据

# 使用jq风格查询
sq '.actor | .first_name, .last_name'

# 使用原生SQL查询
sq sql 'SELECT first_name, last_name FROM actor'

检查数据源结构

# 查看数据源结构
sq inspect

# 查看特定表结构
sq inspect .actor

完整示例

示例1:查询并导出CSV

# 查询actor表并导出为CSV
sq '.actor | .actor_id, .first_name, .last_name' --csv --output actors.csv

示例2:跨数据源连接

# 假设我们有一个CSV文件和一个PostgreSQL数据库
sq add ./employees.csv
sq add postgres://user:pass@localhost/mydb

# 执行跨源连接查询
sq '@csv.employees | join(@pg.employees, .id) | .name, .department'

示例3:使用Go代码调用sq库

package main

import (
	"fmt"
	"log"
	
	"github.com/neilotoole/sq/libsq"
)

func main() {
	// 创建sq实例
	app := libsq.New()
	
	// 添加数据源
	err := app.AddSource("sakila", "sqlite3:///path/to/sakila.db")
	if err != nil {
		log.Fatal(err)
	}
	
	// 执行查询
	result, err := app.Query("sakila", ".actor | .first_name, .last_name")
	if err != nil {
		log.Fatal(err)
	}
	
	// 输出结果
	fmt.Println(result)
}

主要功能

  1. 数据查询:支持jq风格和原生SQL查询语法
  2. 数据转换:支持JSON、CSV、Excel等多种格式转换
  3. 跨源操作:可以在不同数据源之间进行连接查询
  4. 数据导入导出:支持将查询结果插入到其他数据库表
  5. 表操作:提供复制、截断和删除表的功能

输出格式

sq支持多种输出格式:

  • --text:文本格式
  • --json:JSON格式
  • --csv/--tsv:CSV/TSV格式
  • --xlsx:Excel格式
  • --html:HTML格式
  • --xml:XML格式

总结

sq是一个功能强大的数据操作工具,特别适合需要在不同数据格式和数据库之间进行转换和查询的场景。它结合了SQL的查询能力和jq的数据处理能力,为数据分析和处理提供了便捷的命令行界面。


更多关于golang SQL和文档数据格式转换插件库sq的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang SQL和文档数据格式转换插件库sq的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang SQL 和文档数据格式转换插件库 sq 的使用

sq 是一个强大的 Go 语言库,用于在 SQL 数据库和文档数据格式(如 JSON、XML 等)之间进行转换。它提供了简洁的 API 来处理数据库查询结果与结构化文档之间的映射。

安装 sq

go get github.com/bokwoon95/sq

基本用法

1. 从数据库查询转换为 JSON

package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	
	_ "github.com/lib/pq"
	"github.com/bokwoon95/sq"
)

type User struct {
	ID       int    `json:"id"`
	Name     string `json:"name"`
	Email    string `json:"email"`
	IsActive bool   `json:"is_active"`
}

func main() {
	// 连接数据库
	db, err := sql.Open("postgres", "user=postgres dbname=test sslmode=disable")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 查询数据
	rows, err := db.Query("SELECT id, name, email, is_active FROM users")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	// 使用 sq 将结果转换为 JSON
	var users []User
	err = sq.FetchAll(rows, &users)
	if err != nil {
		log.Fatal(err)
	}

	// 输出 JSON
	jsonData, err := json.Marshal(users)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(jsonData))
}

2. 从 JSON 插入到数据库

func insertFromJSON(db *sql.DB) error {
	jsonData := `[
		{"name": "Alice", "email": "alice@example.com", "is_active": true},
		{"name": "Bob", "email": "bob@example.com", "is_active": false}
	]`

	var users []User
	err := json.Unmarshal([]byte(jsonData), &users)
	if err != nil {
		return err
	}

	// 使用 sq 批量插入
	_, err = sq.Exec(db, sq.
		InsertInto("users").
		Columns("name", "email", "is_active").
		Values(users...),
	)
	return err
}

高级特性

1. 自定义映射

type CustomUser struct {
	UserID   int    `db:"id" json:"user_id"`
	FullName string `db:"name" json:"full_name"`
	// 其他字段...
}

func customMapping(db *sql.DB) {
	rows, err := db.Query("SELECT id, name FROM users")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	var customUsers []CustomUser
	err = sq.FetchAll(rows, &customUsers)
	if err != nil {
		log.Fatal(err)
	}

	// 输出自定义结构的JSON
	jsonData, _ := json.Marshal(customUsers)
	fmt.Println(string(jsonData))
}

2. 复杂查询构建

func complexQuery(db *sql.DB) {
	// 构建复杂查询
	query := sq.
		Select("u.id", "u.name", "u.email", "COUNT(o.id) AS order_count").
		From("users u").
		LeftJoin("orders o", "o.user_id = u.id").
		GroupBy("u.id", "u.name", "u.email").
		Having("COUNT(o.id) > ?", 5).
		OrderBy("order_count DESC")

	// 执行查询
	rows, err := query.Fetch(db)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	type UserWithOrders struct {
		ID         int    `json:"id"`
		Name       string `json:"name"`
		Email      string `json:"email"`
		OrderCount int    `json:"order_count"`
	}

	var results []UserWithOrders
	err = sq.FetchAll(rows, &results)
	if err != nil {
		log.Fatal(err)
	}

	jsonData, _ := json.Marshal(results)
	fmt.Println(string(jsonData))
}

性能优化技巧

  1. 批量操作:使用 sq 的批量插入/更新功能提高性能
  2. 预编译语句:对频繁执行的查询使用预编译语句
  3. 流式处理:对于大数据集,使用流式处理避免内存溢出
func batchInsert(db *sql.DB, users []User) error {
	_, err := sq.Exec(db, sq.
		InsertInto("users").
		Columns("name", "email", "is_active").
		Values(users...),
	)
	return err
}

func streamProcessing(db *sql.DB) error {
	rows, err := db.Query("SELECT * FROM large_table")
	if err != nil {
		return err
	}
	defer rows.Close()

	var item struct {
		ID   int
		Data string
	}
	
	for rows.Next() {
		err := sq.Fetch(rows, &item)
		if err != nil {
			return err
		}
		// 处理每个项目而不是加载到内存
		fmt.Println(item)
	}
	return nil
}

sq 库提供了强大而灵活的工具来处理 SQL 和文档数据格式之间的转换,通过合理使用可以大大简化数据持久层的工作。

回到顶部