Go语言库系列之dotsql

导读:能单独拎出SQL文件的某一行或几行执行,是不是非常有趣?今天我们来介绍一下这个有意思的库--dotsql。

背景介绍

dotsql不是ORM,也不是SQL查询语句的构建器,而是可以在一个SQL文件中拎出某几行来执行的工具,非常类似于ini配置文件的读取。如果还不理解,我们来看如下内容。

-- name: create-users-table
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    name VARCHAR(255),
    email VARCHAR(255)
);

-- name: create-user
INSERT INTO users (name, email) VALUES(?, ?)

-- name: find-users-by-email
SELECT id,name,email FROM users WHERE email = ?

-- name: find-one-user-by-email
SELECT id,name,email FROM users WHERE email = ? LIMIT 1

-- name: drop-users-table
DROP TABLE users

上面是SQL文件中定义的语句,我们可以很清晰地看出,每条语句上方都以-- name的方式打上了“注解”,而作为开发人员,可以根据打了标记的名称挑选语句执行。

快速上手

准备工作

目录结构概览

.
├── data.sql
├── go.mod
├── go.sum
└── main.go

初始化项目

go mod init dotsql

创建data.sql文件,键入如下SQL,只是示例,内容可以自定义。

-- name: create-users-table
DROP TABLE IF EXISTS users;
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    name VARCHAR(255),
    email VARCHAR(255)
);

-- name: create-user
INSERT INTO users (name, email) VALUES(?, ?)

-- name: find-users-by-email
SELECT id,name,email FROM users WHERE email = ?

-- name: find-one-user-by-email
SELECT id,name,email FROM users WHERE email = ? LIMIT 1

--name: drop-users-table
DROP TABLE users

为了方便,我们用sqlite来演示,并存储在内存当中,所以要先安装sqlite驱动

go get github.com/mattn/go-sqlite3

代码演示

现在来写代码,导入go-sqlite3库

import _ "github.com/mattn/go-sqlite3"

获取sqlite3的数据库句柄

db, _ := sql.Open("sqlite3", ":memory:")

加载data.sql文件

dot, _ := dotsql.LoadFromFile("data.sql")

挑选文件中的一个标签来执行,Exec方法的第一个参数需要传入句柄

dot.Exec(db, "create-users-table")

从注释可以找到对应的语句,是一个创建表的操作

-- name: create-users-table
DROP TABLE IF EXISTS users;
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    name VARCHAR(255),
    email VARCHAR(255)
);

再来执行第二条语句,插入表数据

dot.Exec(db, "create-user", "User Name", "[email protected]")

我们再来尝试查询表数据,这里要注意,目前所有的操作都是基于定义的标签来选择执行的

	rows, _ := dot.Query(db, "find-users-by-email", "[email protected]")
	var (
		id    int
		name  string
		email string
	)
	for rows.Next() {
		rows.Scan(&id, &name, &email)
		fmt.Println(id, name, email)
	}

Query方法返回的是*sql.Rows类型,同学们可以自行遍历取值测试,大功告成!

其他玩法

我们可以先预准备SQL语句,再在合适的时机执行

stmt, err := dot.Prepare(db, "drop-users-table")
result, err := stmt.Exec()

同样,我们也可以将多个SQL文件合并再进行取值操作

dot1, err := dotsql.LoadFromFile("queries1.sql")
dot2, err := dotsql.LoadFromFile("queries2.sql")
dot := dotsql.Merge(dot1, dot2)


感谢大家的观看,如果觉得文章对你有所帮助,欢迎关注公众号「平也」,聚焦Go语言与技术原理。

原文地址:https://www.cnblogs.com/enochzzg/p/12620058.html

时间: 2024-11-02 10:37:57

Go语言库系列之dotsql的相关文章

Go语言库系列之aurora

背景介绍 今天跟大家推荐一款可以给终端输出上色的工具--aurora. 极速上手 准备工作 初始化项目 go mod init aurora 演示项目结构 . ├── go.mod ├── go.sum └── main.go 安装aurora包 go get -u github.com/logrusorgru/aurora 代码演示 首先引入aurora库 import . "github.com/logrusorgru/aurora" 输出一个品红颜色的内容,Magenta是以颜色

Go语言库系列之flag

背景 终端(命令行)操作是程序员的必备技能,但是你知道怎么通过golang制作出如下命令吗? $ flag girl -h Usage of girl: -height int 身高 (default 140) $ flag girl --height 170 恭喜你获得了身高 170 的女朋友 极速上手 整个实现非常简单,只需要5个步骤 第一步,引库 import "flag" 第二步,定义变量 定义该变量的作用是存储命令行参数传来的值 var height int 第三步,配置命令

python第三方库系列之十七--multiprocessing库

说到并发,我们想到多线程和多进程. 那到底使用多进程还是多线程呢?这得看情况.我们的程序一般分为: 1)耗网络的(有很大一部分时间是在网络交互): 2)耗CPU的(得充分利用多核) 在第一种情况,时间大部分被网络延时占用,所以使用多线程和多进程都差不多. 在第二种情况,时间的长短由CPU是否被充分利用决定,看<python第三方库系列之十二--多线程threading库>可知,多线程会出现锁机制,所以多进程更胜一筹,充分利用了CPU,节省了时间. 以下是一个多进程例子: #coding=utf

C++语言笔记系列之十二——C++的继承

C++的继承 1.继承方式 public(公有继承) 派生类中的成员可以访问基类的public成员和protected成员,但不能访问基类的private成员. 派生类的对象只能访问基类的public成员. protected(保护继承),private(私有继承) 派生类中的成员可以访问基类的public成员和protected成员,但不能访问基类的private成员. 派生类的对象不能访问基类的任何成员. 2.例子 example 1: #include <iostream.h> clas

22Python标准库系列之Redis模块

Python标准库系列之Redis模块 What is redis? Redis is an open source (BSD licensed), in-memory data structure store, used as database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, b

C++语言笔记系列之十六——赋值兼容规则&amp;多继承的二义性

1.赋值兼容规则 (1)派生类对象可以给基类对象赋值,这种情况下派生类对象将从基类继承的成员的值赋值给一个基类对象:但是不允许将一个基类的对象赋值给一个派生类. (2)可以将派生类对象的地址赋给基类指针,使基类指针指向派生类对象,通过基类指针引用成员时只可以引用派生类从基类继承而来的成员,而不允许引用派生类的新成员. (3)引用与指针相同. 2.多继承 (1)一个派生类从两个以上的基类中去继承. (2)说明: class 派生类名:继承方式 基类1, 继承方式 基类2,...... {派生类成员

C++语言笔记系列之十七——虚基类

1.虚基类 考虑这样一种情况:当某个类的部分或者全部直接基类是另一个共同基类派生而来,这些直接基类从上一级基类继承而来的成员就一定拥有相同的名称,这样就会产生二义性问题. 解决办法:当派生类和直接基类产生了二义性问题-->加类的作用域. 当派生类和间接基类产生了二义性问题-->虚基类. 2.虚基类的说明: class 派生类名:virtual 访问权限 基类名 {派生类定义}; 注意:在定义派生类时将需要继承的基类进行虚化声明,虚基类的说明在派生类的定义中完成. 作用:将基类说明为虚基类之后,

1Python标准库系列之模块介绍

Python标准库系列之模块介绍 Python的模块其实就是封装了一个或者多个功能的代码集合,以便于重用,模块可以是一个文件也可以是一个目录,目录的形式称作包. 模块分类 内置模块 内置模块可以理解成当你安装好python环境之后,直接可以使用import导入的就是内置模块,默认模块路径为:C:\Python35\lib,你也可以通过以下方式获取内置模块的路径:  # 导入sys模块  >>> import sys  # 最后一个目录就是内置模块的路径  >>> for

C++语言笔记系列之十三——派生类构造函数的调用

1.派生类构造函数的调用 (1)一个基类的所有数据成员均被派生类继承.创建一个派生类对象时,系统在为派生类对象分配单元时一定要为其基类数据成员分配子空间. (2)一个派生类对象在创建时不仅要调用派生类构造函数,而且要调用基类构造函数. 派生类中的数据成员在派生类中构造. 基类中的数据成员在基类中构造. 原因: A.构造函数不继承. B.派生类的构造函数必须通过调用基类的构造函数完成基类数据成员的初始化. C.若派生类中含有子对象,必须调用子对象的构造函数. 2.派生类的构造函数 派生类名(总参数