{"id":13413672,"url":"https://github.com/rushteam/gosql","last_synced_at":"2025-09-27T13:30:29.943Z","repository":{"id":37096626,"uuid":"259263887","full_name":"rushteam/gosql","owner":"rushteam","description":"golang orm and sql builder","archived":false,"fork":false,"pushed_at":"2022-06-17T09:34:11.000Z","size":384,"stargazers_count":179,"open_issues_count":7,"forks_count":22,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-01-11T05:02:14.455Z","etag":null,"topics":["awesome","db","gin","golang","golang-library","gorm","gosql","orm","sql-builder","sqlbuilder","sqlx","xorm"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rushteam.png","metadata":{"files":{"readme":"README-ZH.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-27T09:16:29.000Z","updated_at":"2025-01-06T07:04:30.000Z","dependencies_parsed_at":"2022-06-24T13:15:16.852Z","dependency_job_id":null,"html_url":"https://github.com/rushteam/gosql","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rushteam%2Fgosql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rushteam%2Fgosql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rushteam%2Fgosql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rushteam%2Fgosql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rushteam","download_url":"https://codeload.github.com/rushteam/gosql/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234338057,"owners_count":18816449,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["awesome","db","gin","golang","golang-library","gorm","gosql","orm","sql-builder","sqlbuilder","sqlx","xorm"],"created_at":"2024-07-30T20:01:46.046Z","updated_at":"2025-09-27T13:30:29.657Z","avatar_url":"https://github.com/rushteam.png","language":"Go","funding_links":[],"categories":["ORM","SQL Builders","Go","网络相关库","Relational Databases"],"sub_categories":["HTTP Clients","HTTP客户端","ORM","OpenGL"],"readme":"# gosql\n\n[![GoTest](https://github.com/rushteam/gosql/workflows/Go/badge.svg)](https://github.com/rushteam/gosql/actions)\n[![GoDoc](https://godoc.org/github.com/rushteam/gosql?status.svg)](https://pkg.go.dev/github.com/rushteam/gosql)\n[![codecov](https://codecov.io/gh/rushteam/gosql/branch/master/graph/badge.svg)](https://codecov.io/gh/rushteam/gosql)\n[![Go Report Card](https://goreportcard.com/badge/github.com/rushteam/gosql)](https://goreportcard.com/report/github.com/rushteam/gosql)\n[![LICENSE](https://img.shields.io/github/license/rushteam/gosql)](https://github.com/rushteam/gosql/blob/master/LICENSE)\n\nA easy ORM for golang\n\ngosql 是一个用golang实现的数据库操作类库\n\n## Feature 功能\n\n* Golang-style SQL builder go语言风格sql生成\n* Unlimited nesting query 查询条件无限嵌套\n* Reading and Writing Separation 读写分离\n* Delay connection creation 延迟创建连接\n* ORM maping to sturct ORM映射结构体\n* Transactions 事务支持\n* Versatile 功能多样的\n* Clean Code 简洁的代码\n* Bulk Insert 支持批量插入\n\n## Structure 结构\n\n* db.go: defined base struct define 基本结构定义\n* pool.go: db manager 管理db\n* session.go: session and maping to model 会话和模型\n* builder.go: for building SQL 构建sql\n* scanner/*: mapping struct and scan 映射模型\n\n## Why build this wheels 为什么造轮子\n\n几乎是翻遍github上所有开源的使用golang实现的操作数据库类)使用起来总有不顺手的地方,例如:\n\ngorm不支持读写分离,关联表使用频率少\n\ngendry 是didi开源的一款,比较简洁但部分语法怪异 如group by 和 limit 依赖字段的约定\n\nsqlx 相比起来不错,但语法不够简洁,不支持读写分离,\n\ngosql 目前仅支持mysql （关键是`符号的处理，以及一些特殊语法，后期可能会考虑兼容pgsql等\n\n本数据库参阅了大量现有数据库架构,参阅各种文献,自定义语法习惯,从零实现\n\n其中灵感来自:分模块的灵感来自gendry,标签读取部分参考gorm,拼装sql的语法来自于我之前写的php的操作db库\n\n## DEMO 例子\n\n为了展示gosql的能力,先展示个例子:\nLet's look a demo:\n\n```sql\nSELECT DISTINCT *\nFROM `tbl1`.`t1`\n    JOIN `tbl3` ON `a` = `b`\nWHERE (`t1`.`status` = ?\n    AND `name` = ?\n    AND `nick` != ?\n    AND `role1` IN (?, ?, ?, ?)\n    AND `role2` NOT IN (?, ?, ?, ?)\n    AND `card1` IN (?)\n    AND `card2` NOT IN (?)\n    AND (`age` \u003e ?\n        AND `age` \u003c ?)\n    AND v1 = 1\n    AND v2 = ?\n    AND `desc` LIKE ?\n    AND `desc` NOT LIKE ?\n    AND EXISTS (\n        SELECT 1\n    )\n    AND NOT EXISTS (\n        SELECT *\n        FROM `tbl2`.`t2`\n        WHERE `t2`.`id` = ?\n    ))\nGROUP BY `class,group`\nHAVING `class` = ?\nORDER BY `score desc`, `name asc`\nLIMIT 10, 30\nFOR UPDATE\n```\n\n```golang\n    s := gosql.NewSQLSegment()\n    s.Flag(\"DISTINCT\")\n    s.Field(\"*\")\n    s.Table(\"tbl1.t1\")\n    s.Where(\"t1.status\", \"0\")\n    s.Where(\"name\", \"jack\")\n    s.Where(\"[!=]nick\", \"tom\")\n    s.Where(\"[in]role1\", []string{\"1\", \"2\", \"3\", \"4\"})\n    s.Where(\"[!in]role2\", []string{\"1\", \"2\", \"3\", \"4\"})\n    s.Where(\"[in]card1\", 1)\n    s.Where(\"[!in]card2\", 1)\n    s.Where(func(s *Clause) {\n        s.Where(\"[\u003e]age\", \"20\")\n        s.Where(\"[\u003c]\", \"50\")\n    })\n    s.Where(\"v1 = 1\")\n    s.Where(\"[#]v2 = ?\", 2)\n    s.Join(\"tbl3\", \"a\", \"=\", \"b\")\n    s.Having(\"class\", \"one\")\n    s.Where(\"[~]desc\", \"student\")\n    s.Where(\"[!~]desc\", \"teacher\")\n    s.Where(\"[exists]my_card\", \"select 1\")\n    s.Where(\"[!exists]my_card2\", func(s *SQLSegments) {\n        s.Table(\"tbl2.t2\")\n        s.Where(\"t2.id\", 10000)\n    })\n    s.GroupBy(\"class,group\")\n    s.OrderBy(\"score desc\", \"name asc\")\n    s.Limit(30)\n    s.Offset(10)\n    s.ForUpdate()\n    fmt.Println(s.BuildSelect())\n```\n\n## Getting Started 开始使用\n\n```golang\npackage main\n\nimport (\n    \"fmt\"\n\n    _ \"github.com/go-sql-driver/mysql\"\n    \"github.com/rushteam/gosql\"\n)\n\ntype UserModel struct {\n    ID   int    `db:\"id\"`\n    Name string `db:\"name\"`\n}\n\nfunc (u *UserModel) TableName() string {\n    return \"my_user\"\n}\n\nfunc main() {\n    db := gosql.NewCluster(\n        gosql.AddDb(\"mysql\", \"user:password@tcp(127.0.0.1:3306)/test?parseTime=true\u0026readTimeout=3s\u0026writeTimeout=3s\u0026timeout=3s\"),\n    )\n    user := \u0026UserModel{}\n    err := db.Fetch(user, gosql.Where(\"id\", 1), gosql.Where(\"[like]name\", \"j%\"))\n    if err != nil {\n        fmt.Println(err)\n    }\n    fmt.Println(user)\n}\n\n```\n\n## Doc 文档\n\n## Debug\n\n```golang\n//this code will be start at debug mode and the sql will be print\ngosql.Debug = true\n```\n\n## Struct Model\n\nTo define a model structure, just use the struct syntax.\n\n### Simple define a model\n\n```golang\ntype User struct {\n    ID int64\n    Age int\n    Name string\n    CreatedAt time.Time\n}\n```\n\nUsually define a Struct can be used as a model, gosql will parse out the table name, field mapping relationship,etc.\n\n定义一个普通的结构体就可以被作为一个model , gosql 将会从中解析出表名、字段映射关系等\n\ntable: user\ncolumns: ID,Age,Name,CreatedAt\n\n### Using tag syntax\n\nUse structure tags to customize field mapping\n\n使用结构体tags 可以自定义字段映射\n\n```golang\ntype User struct {\n    ID int64 `db:\"uid,pk\"`\n    Age int `db:\"age\"`\n    Name string `db:\"nickname\"`\n    CreatedAt time.Time `db:\"created_at\"`\n}\n```\n\ntable: user\ncolumns: uid,age,nickname,created_at\npk: uid\n\n### Using custom table name\n\nImplement \"TabbleName\" method to specify the table name\n\n通过实现 TabbleName 方法来指定一个表名\n\n```golang\ntype User struct {\n    ID int64 `db:\"uid,pk\"`\n    Age int `db:\"age\"`\n    Name string `db:\"nickname\"`\n    CreatedAt time.Time `db:\"created_at\"`\n}\nfunc (u *User) TableName() string {\n    return \"my_user\"\n}\n```\n\ntable: my_user\n\n## Auto\n\n## Exec\n\n### INSERT\n\ndb.Insert(dst interface{}, opts ...Option) (Result, error)\n\n```golang\nuser := \u0026UserModel{}\nuser.Name = \"jack\"\nret,err := db.Insert(\u0026user)\n```\n\nbatch insert\n\n```golang\nusers := []UserModel{}\nu1 := UserModel{Name:\"jack\"}\nu2 := UserModel{Name:\"Tom\"}\nusers = append(users,u1)\nusers = append(users,u2)\nret,err := db.Insert(users)\n```\n\n### REPALCE\n\ndb.Replace(dst interface{}, opts ...Option) (Result, error)\n\n```golang\nuser := \u0026UserModel{}\nuser.Name = \"jack\"\nret,err := db.Replace(\u0026user,gosql.Where(\"id\",1))\n```\n\n### UPDATE\n\nUpdate(dst interface{}, opts ...Option) (Result, error)\n\n```golang\nuser := \u0026UserModel{}\nuser.Name = \"jack Ma\"\nret,err := db.Update(\u0026user,gosql.Where(\"id\",1))\n```\n\n### DELETE\n\ndb.Delete(dst interface{}, opts ...Option) (Result, error)\n\n```golang\nuser := \u0026UserModel{}\nret,err := db.Delete(\u0026user,gosql.Where(\"id\",1))\n//sql: delete from my_user where id = 1\n```\n\n## QUERY\n\n### Get a record: db.Fetch(dst interface{}, opts ...Option) error\n\n```golang\nuser := \u0026UserModel{}\nerr := db.Fetch(user,\n    gosql.Columns(\"id\",\"name\"),\n    gosql.Where(\"id\", 1),\n    gosql.Where(\"[like]name\", \"j%\"),\n    gosql.OrWhere(func(s *Clause) {\n        s.Where(\"[\u003e=]score\", \"90\")\n        s.Where(\"[\u003c=]age\", \"100\")\n    }),\n    gosql.GroupBy(\"type\"),\n    gosql.OrderBy(\"score DESC\"),\n)\n```\n\n### Get multiple records: db.FetchAll(dst interface{}, opts ...Option) error\n\n```golang\nvar userList []UserModel\nerr := db.FetchAll(\u0026userList,\n    gosql.Columns(\"id\",\"name\"),\n    gosql.Where(\"id\", 1),\n    gosql.Where(\"[like]name\", \"j%\"),\n    gosql.OrWhere(func(s *Clause) {\n        s.Where(\"[\u003e]score\", \"90\")\n        s.Where(\"[\u003c]score\", \"100\")\n    }),\n    gosql.GroupBy(\"type\"),\n    gosql.OrderBy(\"score DESC\"),\n    gosql.Offset(0),\n    gosql.Limit(10),\n)\n```\n\n## OPTION\n\n### WHERE\n\n#### gosql.Where(\"id\",1)\n\n```golang\ngosql.Where(\"id\",1)\n//sql: id = 1\n```\n\n#### gosql.Where(\"[\u003e]age\",18)\n\n```golang\ngosql.Where(\"[\u003e]age\",18)\n//sql: age \u003e 18\n```\n\n#### gosql.Where(\"[in]id\",[]int{1,2})\n\n```golang\ngosql.Where(\"[in]id\",[]int{1,2})\n//sql: id in (1,2)\n```\n\n#### gosql.Where(\"[!in]id\",[]int{1,2})\n\n```golang\ngosql.Where(\"[!in]id\",[]int{1,2})\n//sql: id not in (1,2)\n```\n\n#### gosql.Where(\"[~]name\",\"ja%\")\n\n```golang\ngosql.Where(\"[~]name\",\"ja%\")\n//sql: name like 'ja%'\n```\n\n#### gosql.Where(\"[!~]name\",\"ja%\")\n\n```golang\ngosql.Where(\"[!~]name\",\"ja%\")\n//sql: name not like 'ja%'\n```\n\n### 条件表达式 [?]\n\n#### [=] equal\n\n```golang\ngosql.Where(\"[=]id\",1)\n//sql: id = 1\n```\n\n#### [!=] not equal\n\n```golang\ngosql.Where(\"[!=]id\",1)\n//sql: id != 1\n```\n\n#### [\u003e] greater than\n\n```golang\ngosql.Where(\"[\u003e]id\",1)\n//sql: id \u003e 1\n```\n\n#### [\u003e=] greater or equal\n\n```golang\ngosql.Where(\"[\u003e=]id\",1)\n//sql: id \u003e= 1\n```\n\n#### [\u003c] less\n\n```golang\ngosql.Where(\"[\u003c]id\",1)\n//sql: id \u003c 1\n```\n\n#### [\u003c=] less or equal\n\n```golang\ngosql.Where(\"[\u003c=]id\",1)\n//sql: id \u003c= 1\n```\n\n#### [in] in\n\n```golang\ngosql.Where(\"[in]id\",[]int{1,2})\n//sql: id in (1,2)\n```\n\n#### [!in] not in\n\n```golang\ngosql.Where(\"[!in]id\",[]int{1,2})\n//sql: id not in (1,2)\n```\n\n#### [is] is null\n\n```golang\ngosql.Where(\"[is]name\",nil)\n//sql: name is null\n```\n\n#### [!is] not is null\n\n```golang\ngosql.Where(\"[!is]name\",\"\")\n//sql: id is not \"\"\n```\n\n#### [exists] exists\n\n```golang\ngosql.Where(\"[exists]name\",\"select 1\")\n//sql: name exists(select 1)\n```\n\n#### [!exists] not exists\n\n```golang\ngosql.Where(\"[!exists]name\",\"select 1\")\n//sql: name not exists(select 1)\n```\n\n#### [#] sql\n\n```golang\ngosql.Where(\"[#]age=age-1\")\n//sql: age = age-1\n```\n\n## Raw SQL: db.Query()\n\n```golang\nrows,err := db.Query(\"select * from my_user where id = ?\",1)\n//sql: select * from my_user where id = 1\n```\n\n## select primary or replica\n\n### change to primary: db.Primary()\n\n```golang\ndb := db.Primary()\ndb.Fetch(...)\n```\n\n### change to replica: db.Replica()\n\n```golang\ndb := db.Replica()\ndb.Fetch(...)\n```\n\n## builder of API\n\n### 创建语句\n\n**用法** builder.New()\n\n例子 s := builder.New()\n\n### 设置Flag builder.Flag(f string)\n\n设置一个falg,非必须\n\n**用法** s.Flag(string)\n\n例子 s := builder.New().Flag(\"\")\n\n### 指定字段 builder.Field(fields string)\n\n指定查询字段 不指定 默认为 *\n\n**用法** s.Field(\"*\")\n\n### 指定表名 builder.Table(tbl string)\n\n**用法** s.Table(\"tbl1.t1\")\n\n### 查询条件\n\n* 普通查询 s.Where(key string, val inferface{})\n\n* 等于查询\n\n **用法** s.Where(\"t1.status\", \"0\")\n\n **等效SQL** t1.status = 0\n\n* 不等于查询\n\n**用法** s.Where(\"[!=]t1.status\", \"0\")\n\n**等效SQL** t1.status != 0\n\n* IN查询\n\n**用法** s.Where(\"[in]sts\", []string{\"a\", \"b\", \"c\"})\n\n**等效SQL** t1.type in (a,b,c)\n\n* NOT IN查询\n\n**用法** s.Where(\"[!in]sts\", []string{\"a\", \"b\", \"c\"})\n\n**等效SQL** t1.type not in (a,b,c)\n\n* 复杂条件查询\n\n**用法** .Where(func(s *builder.Clause){}\n\n```golang\ns.Where(\"[!]t1.a\",1).Where(func(s *builder.Clause){\n    s.Where(\"t1.b\",1)\n    s.OrWhere(\"t1.c\",1)\n})\n```\n\n**等效SQL**  t1.a != 1  and (t1.b = 1 or t1.c = 1)\n\n* GROUP BY 分类\n\n**用法**  s.GroupBy(\"id\")\n\n**等效SQL** group by `id`\n\n* ORDER BY 排序\n\n**用法**  s.OrderBy(\"id desc\", \"age asc\")\n\n**等效SQL** order by `id` desc\n\n* 限制条数\n\n**用法**  s.Limit(30)\n\n**等效SQL** limit 30\n\n* 偏移条数\n\n**用法**  s.Offset(10)\n\n**等效SQL** offset 30\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frushteam%2Fgosql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frushteam%2Fgosql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frushteam%2Fgosql/lists"}