7ddd2034 by astaxie

orm: delete the old docs

1 parent e7fcb824
1 ## 命令模式
2
3 注册模型与数据库以后,调用 RunCommand 执行 orm 命令
4
5 ```go
6 func main() {
7 // orm.RegisterModel...
8 // orm.RegisterDataBase...
9 ...
10 orm.RunCommand()
11 }
12 ```
13
14 ```bash
15 go build main.go
16 ./main orm
17 # 直接执行可以显示帮助
18 # 如果你的程序可以支持的话,直接运行 go run main.go orm 也是一样的效果
19 ```
20
21 ## 自动建表
22
23 ```bash
24 ./main orm syncdb -h
25 Usage of orm command: syncdb:
26 -db="default": DataBase alias name
27 -force=false: drop tables before create
28 -v=false: verbose info
29 ```
30
31 使用 `-force=1` 可以 drop table 后再建表
32
33 使用 `-v` 可以查看执行的 sql 语句
34
35 ## 打印建表SQL
36
37 ```bash
38 ./main orm sqlall -h
39 Usage of orm command: syncdb:
40 -db="default": DataBase alias name
41 ```
42
43 默认使用别名为 default 的数据库
1 ## Custom Fields
2
3 TypeBooleanField = 1 << iota
4
5 // string
6 TypeCharField
7
8 // string
9 TypeTextField
10
11 // time.Time
12 TypeDateField
13 // time.Time
14 TypeDateTimeField
15
16 // int16
17 TypeSmallIntegerField
18 // int32
19 TypeIntegerField
20 // int64
21 TypeBigIntegerField
22 // uint16
23 TypePositiveSmallIntegerField
24 // uint32
25 TypePositiveIntegerField
26 // uint64
27 TypePositiveBigIntegerField
28
29 // float64
30 TypeFloatField
31 // float64
32 TypeDecimalField
33
34 RelForeignKey
35 RelOneToOne
36 RelManyToMany
37 RelReverseOne
38 RelReverseMany
...\ No newline at end of file ...\ No newline at end of file
1 ## 模型定义
2
3 复杂的模型定义不是必须的,此功能用作数据库数据转换和[自动建表](Cmd.md#自动建表)
4
5 默认的表名使用驼峰转蛇形,比如 AuthUser -> auth_user
6
7 **自定义表名**
8
9 ```go
10 type User struct {
11 Id int
12 Name string
13 }
14
15 func (u *User) TableName() string {
16 return "auth_user"
17 }
18 ```
19
20 如果[前缀设置](Orm.md#registermodelwithprefix)`prefix_`那么表名为:prefix_auth_user
21
22 ## Struct Tag 设置参数
23 ```go
24 orm:"null;rel(fk)"
25 ```
26
27 多个设置间使用 `;` 分隔,设置的值如果是多个,使用 `,` 分隔。
28
29 #### 忽略字段
30
31 设置 `-` 即可忽略 struct 中的字段
32
33 ```go
34 type User struct {
35 ...
36 AnyField string `orm:"-"`
37 ...
38 ```
39
40 #### auto
41
42 当 Field 类型为 int, int32, int64 时,可以设置字段为自增健
43
44 当模型定义里没有主键时,符合上述类型且名称为 `Id` 的 Field 将被视为自增健。
45
46 #### pk
47
48 设置为主键,适用于自定义其他类型为主键
49
50 #### null
51
52 数据库表默认为 `NOT NULL`,设置 null 代表 `ALLOW NULL`
53
54 #### blank
55
56 设置 string 类型的字段允许为空,否则 clean 会返回错误
57
58 #### index
59
60 为字段增加索引
61
62 #### unique
63
64 为字段增加 unique 键
65
66 #### column
67
68 为字段设置 db 字段的名称
69 ```go
70 Name `orm:"column(user_name)"`
71 ```
72 #### default
73
74 为字段设置默认值,类型必须符合
75 ```go
76 type User struct {
77 ...
78 Status int `orm:"default(1)"`
79 ```
80 #### size
81
82 string 类型字段默认为 varchar(255)
83
84 设置 size 以后,db type 将使用 varchar(size)
85
86 ```go
87 Title string `orm:"size(60)"`
88 ```
89 #### digits / decimals
90
91 设置 float32, float64 类型的浮点精度
92 ```go
93 Money float64 `orm:"digits(12);decimals(4)"`
94 ```
95 总长度 12 小数点后 4 位 eg: `99999999.9999`
96
97 #### auto_now / auto_now_add
98 ```go
99 Created time.Time `auto_now_add`
100 Updated time.Time `auto_now`
101 ```
102 * auto_now 每次 model 保存时都会对时间自动更新
103 * auto_now_add 第一次保存时才设置时间
104
105 对于批量的 update 此设置是不生效的
106
107 #### type
108
109 设置为 date 时,time.Time 字段的对应 db 类型使用 date
110
111 ```go
112 Created time.Time `orm:"auto_now_add;type(date)"`
113 ```
114
115 设置为 text 时,string 字段对应的 db 类型使用 text
116
117 ```go
118 Content string `orm:"type(text)"`
119 ```
120
121 ## 表关系设置
122
123 #### rel / reverse
124
125 **RelOneToOne**:
126 ```go
127 type User struct {
128 ...
129 Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
130 ```
131 对应的反向关系 **RelReverseOne**:
132 ```go
133 type Profile struct {
134 ...
135 User *User `orm:"reverse(one)" json:"-"`
136 ```
137 **RelForeignKey**:
138 ```go
139 type Post struct {
140 ...
141 User*User `orm:"rel(fk)"` // RelForeignKey relation
142 ```
143 对应的反向关系 **RelReverseMany**:
144 ```go
145 type User struct {
146 ...
147 Posts []*Post `orm:"reverse(many)" json:"-"` // fk 的反向关系
148 ```
149 **RelManyToMany**:
150 ```go
151 type Post struct {
152 ...
153 Tags []*Tag `orm:"rel(m2m)"` // ManyToMany relation
154 ```
155 对应的反向关系 **RelReverseMany**:
156 ```go
157 type Tag struct {
158 ...
159 Posts []*Post `orm:"reverse(many)" json:"-"`
160 ```
161 #### rel_table / rel_through
162
163 此设置针对 `orm:"rel(m2m)"` 的关系字段
164
165 rel_table 设置自动生成的 m2m 关系表的名称
166 rel_through 如果要在 m2m 关系中使用自定义的 m2m 关系表
167 通过这个设置其名称,格式为 pkg.path.ModelName
168 eg: app.models.PostTagRel
169 PostTagRel 表需要有到 Post 和 Tag 的关系
170
171 当设置 rel_table 时会忽略 rel_through
172
173 #### on_delete
174
175 设置对应的 rel 关系删除时,如何处理关系字段。
176
177 cascade 级联删除(默认值)
178 set_null 设置为 NULL,需要设置 null = true
179 set_default 设置为默认值,需要设置 default 值
180 do_nothing 什么也不做,忽略
181
182 ```go
183 type User struct {
184 ...
185 Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
186 ...
187 type Profile struct {
188 ...
189 User *User `orm:"reverse(one)" json:"-"`
190
191 // 删除 Profile 时将设置 User.Profile 的数据库字段为 NULL
192 ```
193
194
195 ## 模型字段与数据库类型的对应
196
197 在此列出 orm 推荐的对应数据库类型,自动建表功能也会以此为标准。
198
199 默认所有的字段都是 **NOT NULL**
200
201 #### MySQL
202
203 | go |mysql
204 | :--- | :---
205 | int, int32, int64 - 设置 auto 或者名称为 `Id` 时 | integer AUTO_INCREMENT
206 | bool | bool
207 | string - 默认为 size 255 | varchar(size)
208 | string - 设置 type(text) 时 | longtext
209 | time.Time - 设置 type 为 date 时 | date
210 | time.TIme | datetime
211 | byte | tinyint unsigned
212 | rune | integer
213 | int | integer
214 | int8 | tinyint
215 | int16 | smallint
216 | int32 | integer
217 | int64 | bigint
218 | uint | integer unsigned
219 | uint8 | tinyint unsigned
220 | uint16 | smallint unsigned
221 | uint32 | integer unsigned
222 | uint64 | bigint unsigned
223 | float32 | double precision
224 | float64 | double precision
225 | float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
226
227 #### Sqlite3
228
229 | go | sqlite3
230 | :--- | :---
231 | int, int32, int64 - 设置 auto 或者名称为 `Id` 时 | integer AUTOINCREMENT
232 | bool | bool
233 | string - 默认为 size 255 | varchar(size)
234 | string - 设置 type(text) 时 | text
235 | time.Time - 设置 type 为 date 时 | date
236 | time.TIme | datetime
237 | byte | tinyint unsigned
238 | rune | integer
239 | int | integer
240 | int8 | tinyint
241 | int16 | smallint
242 | int32 | integer
243 | int64 | bigint
244 | uint | integer unsigned
245 | uint8 | tinyint unsigned
246 | uint16 | smallint unsigned
247 | uint32 | integer unsigned
248 | uint64 | bigint unsigned
249 | float32 | real
250 | float64 | real
251 | float64 - 设置 digits, decimals 时 | decimal
252
253 #### PostgreSQL
254
255 | go | postgres
256 | :--- | :---
257 | int, int32, int64 - 设置 auto 或者名称为 `Id` 时 | serial
258 | bool | bool
259 | string - 默认为 size 255 | varchar(size)
260 | string - 设置 type(text) 时 | text
261 | time.Time - 设置 type 为 date 时 | date
262 | time.TIme | timestamp with time zone
263 | byte | smallint CHECK("column" >= 0 AND "column" <= 255)
264 | rune | integer
265 | int | integer
266 | int8 | smallint CHECK("column" >= -127 AND "column" <= 128)
267 | int16 | smallint
268 | int32 | integer
269 | int64 | bigint
270 | uint | bigint CHECK("column" >= 0)
271 | uint8 | smallint CHECK("column" >= 0 AND "column" <= 255)
272 | uint16 | integer CHECK("column" >= 0)
273 | uint32 | bigint CHECK("column" >= 0)
274 | uint64 | bigint CHECK("column" >= 0)
275 | float32 | double precision
276 | float64 | double precision
277 | float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
278
279
280 ## 关系型字段
281
282 其字段类型取决于对应的主键。
283
284 * RelForeignKey
285 * RelOneToOne
286 * RelManyToMany
287 * RelReverseOne
288 * RelReverseMany
...\ No newline at end of file ...\ No newline at end of file
1 SET NAMES utf8;
2 SET FOREIGN_KEY_CHECKS = 0;
3
4 -- ----------------------------
5 -- Table structure for `comment`
6 -- ----------------------------
7 DROP TABLE IF EXISTS `comment`;
8 CREATE TABLE `comment` (
9 `id` int(11) NOT NULL,
10 `post_id` bigint(200) NOT NULL,
11 `content` longtext NOT NULL,
12 `parent_id` int(11) DEFAULT NULL,
13 `status` smallint(4) NOT NULL,
14 `created` datetime NOT NULL,
15 PRIMARY KEY (`id`)
16 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
17
18 -- ----------------------------
19 -- Table structure for `post`
20 -- ----------------------------
21 DROP TABLE IF EXISTS `post`;
22 CREATE TABLE `post` (
23 `id` int(11) NOT NULL,
24 `user_id` int(11) NOT NULL,
25 `title` varchar(60) NOT NULL,
26 `content` longtext NOT NULL,
27 `created` datetime NOT NULL,
28 `updated` datetime NOT NULL,
29 PRIMARY KEY (`id`)
30 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
31
32 -- ----------------------------
33 -- Table structure for `post_tag_rel`
34 -- ----------------------------
35 DROP TABLE IF EXISTS `post_tag_rel`;
36 CREATE TABLE `post_tag_rel` (
37 `id` int(11) NOT NULL,
38 `post_id` int(11) NOT NULL,
39 `tag_id` int(11) NOT NULL,
40 PRIMARY KEY (`id`)
41 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
42
43 -- ----------------------------
44 -- Table structure for `tag`
45 -- ----------------------------
46 DROP TABLE IF EXISTS `tag`;
47 CREATE TABLE `tag` (
48 `id` int(11) NOT NULL,
49 `name` varchar(30) NOT NULL,
50 `status` smallint(4) NOT NULL,
51 PRIMARY KEY (`id`)
52 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
53
54 -- ----------------------------
55 -- Table structure for `user`
56 -- ----------------------------
57 DROP TABLE IF EXISTS `user`;
58 CREATE TABLE `user` (
59 `id` int(11) NOT NULL AUTO_INCREMENT,
60 `user_name` varchar(30) NOT NULL,
61 `email` varchar(100) NOT NULL,
62 `password` varchar(30) NOT NULL,
63 `status` smallint(4) NOT NULL,
64 `is_staff` tinyint(1) NOT NULL,
65 `is_active` tinyint(1) NOT NULL,
66 `created` date NOT NULL,
67 `updated` datetime NOT NULL,
68 `profile_id` int(11) DEFAULT NULL,
69 PRIMARY KEY (`id`)
70 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
71
72 -- ----------------------------
73 -- Table structure for `profile`
74 -- ----------------------------
75 DROP TABLE IF EXISTS `profile`;
76 CREATE TABLE `profile` (
77 `id` int(11) NOT NULL AUTO_INCREMENT,
78 `age` smallint(4) NOT NULL,
79 `money` double NOT NULL,
80 PRIMARY KEY (`id`)
81 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
82
83 SET FOREIGN_KEY_CHECKS = 1;
1 ## 对象的CRUD操作
2
3 对 object 操作简单的三个方法 Read / Insert / Update / Delete
4 ```go
5 o := orm.NewOrm()
6 user := new(User)
7 user.Name = "slene"
8
9 fmt.Println(o.Insert(user))
10
11 user.Name = "Your"
12 fmt.Println(o.Update(user))
13 fmt.Println(o.Read(user))
14 fmt.Println(o.Delete(user))
15 ```
16 ### Read
17 ```go
18 o := orm.NewOrm()
19 user := User{Id: 1}
20
21 err = o.Read(&user)
22
23 if err == sql.ErrNoRows {
24 fmt.Println("查询不到")
25 } else if err == orm.ErrMissPK {
26 fmt.Println("找不到主键")
27 } else {
28 fmt.Println(user.Id, user.Name)
29 }
30 ```
31 ### Insert
32 ```go
33 o := orm.NewOrm()
34 var user User
35 user.Name = "slene"
36 user.IsActive = true
37
38 fmt.Println(o.Insert(&user))
39 fmt.Println(user.Id)
40 ```
41 创建后会自动对 auto 的 field 赋值
42
43 ### Update
44 ```go
45 o := orm.NewOrm()
46 user := User{Id: 1}
47 if o.Read(&user) == nil {
48 user.Name = "MyName"
49 o.Update(&user)
50 }
51 ```
52 ### Delete
53 ```go
54 o := orm.NewOrm()
55 o.Delete(&User{Id: 1})
56 ```
57 Delete 操作会对反向关系进行操作,此例中 Post 拥有一个到 User 的外键。删除 User 的时候。如果 on_delete 设置为默认的级联操作,将删除对应的 Post
58
59 删除以后会清除 auto field 的值
1 ## Orm 使用方法
2
3 beego/orm 的使用例子
4
5 后文例子如无特殊说明都以这个为基础。
6
7 ##### models.go:
8
9 ```go
10 package main
11
12 import (
13 "github.com/astaxie/beego/orm"
14 )
15
16 type User struct {
17 Id int
18 Name string
19 Profile *Profile `orm:"rel(one)"` // OneToOne relation
20 }
21
22 type Profile struct {
23 Id int
24 Age int16
25 User *User `orm:"reverse(one)"` // 设置反向关系(可选)
26 }
27
28 func init() {
29 // 需要在init中注册定义的model
30 orm.RegisterModel(new(User), new(Profile))
31 }
32 ```
33
34 ##### main.go
35
36 ```go
37 package main
38
39 import (
40 "fmt"
41 "github.com/astaxie/beego/orm"
42 _ "github.com/go-sql-driver/mysql"
43 )
44
45 func init() {
46 orm.RegisterDriver("mysql", orm.DR_MySQL)
47
48 orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", 30)
49 }
50
51 func main() {
52 o := orm.NewOrm()
53 o.Using("default") // 默认使用 default,你可以指定为其他数据库
54
55 profile := new(Profile)
56 profile.Age = 30
57
58 user := new(User)
59 user.Profile = profile
60 user.Name = "slene"
61
62 fmt.Println(o.Insert(profile))
63 fmt.Println(o.Insert(user))
64 }
65 ```
66
67 ## 数据库的设置
68
69 目前 orm 支持三种数据库,以下为测试过的 driver
70
71 将你需要使用的 driver 加入 import 中
72
73 ```go
74 import (
75 _ "github.com/go-sql-driver/mysql"
76 _ "github.com/lib/pq"
77 _ "github.com/mattn/go-sqlite3"
78 )
79 ```
80
81 #### RegisterDriver
82
83 三种默认数据库类型
84
85 ```go
86 orm.DR_MySQL
87 orm.DR_Sqlite
88 orm.DR_Postgres
89 ```
90
91 ```go
92 // 参数1 driverName
93 // 参数2 数据库类型
94 // 这个用来设置 driverName 对应的数据库类型
95 // mysql / sqlite3 / postgres 这三种是默认已经注册过的,所以可以无需设置
96 orm.RegisterDriver("mymysql", orm.DR_MySQL)
97 ```
98
99 #### RegisterDataBase
100
101 orm 必须注册一个别名为 `default` 的数据库,作为默认使用。
102
103 ```go
104 // 参数1 数据库的别名,用来在orm中切换数据库使用
105 // 参数2 driverName
106 // 参数3 对应的链接字符串
107 // 参数4 设置最大的空闲连接数,使用 golang 自己的连接池
108 orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", 30)
109 ```
110
111 #### 时区设置
112
113 orm 默认使用 time.Local 本地时区
114
115 * 作用于 orm 自动创建的时间
116 * 从数据库中取回的时间转换成 orm 本地时间
117
118 如果需要的话,你也可以进行更改
119
120 ```go
121 // 设置为 UTC 时间
122 orm.DefaultTimeLoc = time.UTC
123 ```
124
125 orm 在进行 RegisterDataBase 的同时,会获取数据库使用的时区,然后在 time.Time 类型存取的时做相应转换,以匹配时间系统,从而保证时间不会出错。
126
127 **注意:** 鉴于 Sqlite3 的设计,存取默认都为 UTC 时间
128
129 ## 注册模型
130
131 如果使用 orm.QuerySeter 进行高级查询的话,这个是必须的。
132
133 反之,如果只使用 Raw 查询和 map struct,是无需这一步的。您可以去查看 [Raw SQL 查询](Raw.md)
134
135 #### RegisterModel
136
137 将你定义的 Model 进行注册,最佳设计是有单独的 models.go 文件,在他的 init 函数中进行注册。
138
139
140 迷你版 models.go
141 ```go
142 package main
143
144 import "github.com/astaxie/beego/orm"
145
146 type User struct {
147 Id int
148 Name string
149 }
150
151 func init(){
152 orm.RegisterModel(new(User))
153 }
154 ```
155
156 RegisterModel 也可以同时注册多个 model
157
158 ```go
159 orm.RegisterModel(new(User), new(Profile), new(Post))
160 ```
161
162 详细的 struct 定义请查看文档 [模型定义](Models.md)
163
164 #### RegisterModelWithPrefix
165
166 使用表名前缀
167
168 ```go
169 orm.RegisterModelWithPrefix("prefix_", new(User))
170 ```
171
172 创建后的表名为 prefix_user
173
174 ## ORM 接口使用
175
176 使用 orm 必然接触的 Ormer 接口,我们来熟悉一下
177
178 ```go
179 var o Ormer
180 o = orm.NewOrm() // 创建一个 Ormer
181 // NewOrm 的同时会执行 orm.BootStrap (整个 app 只执行一次),用以验证模型之间的定义并缓存。
182 ```
183
184 * type Ormer interface {
185 * [Read(Modeler) error](Object.md#read)
186 * [Insert(Modeler) (int64, error)](Object.md#insert)
187 * [Update(Modeler) (int64, error)](Object.md#update)
188 * [Delete(Modeler) (int64, error)](Object.md#delete)
189 * [M2mAdd(Modeler, string, ...interface{}) (int64, error)](Object.md#m2madd)
190 * [M2mDel(Modeler, string, ...interface{}) (int64, error)](Object.md#m2mdel)
191 * [LoadRel(Modeler, string) (int64, error)](Object.md#loadRel)
192 * [QueryTable(interface{}) QuerySeter](#querytable)
193 * [Using(string) error](#using)
194 * [Begin() error](Transaction.md)
195 * [Commit() error](Transaction.md)
196 * [Rollback() error](Transaction.md)
197 * [Raw(string, ...interface{}) RawSeter](#raw)
198 * [Driver() Driver](#driver)
199 * }
200
201
202 #### QueryTable
203
204 传入表名,或者 Modeler 对象,返回一个 [QuerySeter](Query.md#queryseter)
205
206 ```go
207 o := orm.NewOrm()
208 var qs QuerySeter
209 qs = o.QueryTable("user")
210 // 如果表没有定义过,会立刻 panic
211 ```
212
213 #### Using
214
215 切换为其他数据库
216
217 ```go
218 orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8", 30)
219 orm.RegisterDataBase("db2", "sqlite3", "data.db", 30)
220
221 o1 := orm.NewOrm()
222 o1.Using("db1")
223
224 o2 := orm.NewOrm()
225 o2.Using("db2")
226
227 // 切换为其他数据库以后
228 // 这个 Ormer 对象的其下的 api 调用都将使用这个数据库
229
230 ```
231
232 默认使用 `default` 数据库,无需调用 Using
233
234 #### Raw
235
236 使用 sql 语句直接进行操作
237
238 Raw 函数,返回一个 [RawSeter](Raw.md) 用以对设置的 sql 语句和参数进行操作
239
240 ```go
241 o := NewOrm()
242 var r RawSeter
243 r = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")
244 ```
245
246 #### Driver
247
248 返回当前 orm 使用的 db 信息
249
250 ```go
251 type Driver interface {
252 Name() string
253 Type() DriverType
254 }
255 ```
256
257 ```go
258 orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8", 30)
259 orm.RegisterDataBase("db2", "sqlite3", "data.db", 30)
260
261 o1 := orm.NewOrm()
262 o1.Using("db1")
263 dr := o1.Driver()
264 fmt.Println(dr.Name() == "db1") // true
265 fmt.Println(dr.Type() == orm.DR_MySQL) // true
266
267 o2 := orm.NewOrm()
268 o2.Using("db2")
269 dr = o2.Driver()
270 fmt.Println(dr.Name() == "db2") // true
271 fmt.Println(dr.Type() == orm.DR_Sqlite) // true
272
273 ```
274
275 ## 调试模式打印查询语句
276
277 简单的设置 Debug 为 true 打印查询的语句
278
279 可能存在性能问题,不建议使用在产品模式
280
281 ```go
282 func main() {
283 orm.Debug = true
284 ...
285 ```
286
287 默认使用 os.Stderr 输出日志信息
288
289 改变输出到你自己的 io.Writer
290
291 ```go
292 var w io.Writer
293 ...
294 // 设置为你的 io.Writer
295 ...
296 orm.DebugLog = orm.NewLog(w)
297 ```
298
299 日志格式
300
301 ```go
302 [ORM] - 时间 - [Queries/数据库名] - [执行操作/执行时间] - [SQL语句] - 使用标点 `,` 分隔的参数列表 - 打印遇到的错误
303 ```
304
305 ```go
306 [ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [INSERT INTO `user` (`name`) VALUES (?)] - `slene`
307 [ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.5ms] - [UPDATE `user` SET `name` = ? WHERE `id` = ?] - `astaxie`, `14`
308 [ORM] - 2013-08-09 13:18:16 - [Queries/default] - [db.QueryRow / 0.4ms] - [SELECT `id`, `name` FROM `user` WHERE `id` = ?] - `14`
309 [ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [INSERT INTO `post` (`user_id`,`title`,`content`) VALUES (?, ?, ?)] - `14`, `beego orm`, `powerful amazing`
310 [ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Query / 0.4ms] - [SELECT T1.`name` `User__Name`, T0.`user_id` `User`, T1.`id` `User__Id` FROM `post` T0 INNER JOIN `user` T1 ON T1.`id` = T0.`user_id` WHERE T0.`id` = ? LIMIT 1000] - `68`
311 [ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [DELETE FROM `user` WHERE `id` = ?] - `14`
312 [ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Query / 0.3ms] - [SELECT T0.`id` FROM `post` T0 WHERE T0.`user_id` IN (?) ] - `14`
313 [ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [DELETE FROM `post` WHERE `id` IN (?)] - `68`
314 ```
315
316 日志内容包括 **所有的数据库操作**,事务,Prepare,等
1 ## 高级查询
2
3 orm 以 **QuerySeter** 来组织查询,每个返回 **QuerySeter** 的方法都会获得一个新的 **QuerySeter** 对象。
4
5 基本使用方法:
6 ```go
7 o := orm.NewOrm()
8
9 // 获取 QuerySeter 对象,user 为表名
10 qs := o.QueryTable("user")
11
12 // 也可以直接使用对象作为表名
13 user := new(User)
14 qs = o.QueryTable(user) // 返回 QuerySeter
15 ```
16 ## expr
17
18 QuerySeter 中用于描述字段和 sql 操作符,使用简单的 expr 查询方法
19
20 字段组合的前后顺序依照表的关系,比如 User 表拥有 Profile 的外键,那么对 User 表查询对应的 Profile.Age 为条件,则使用 `Profile__Age` 注意,字段的分隔符号使用双下划线 `__`,除了描述字段, expr 的尾部可以增加操作符以执行对应的 sql 操作。比如 `Profile__Age__gt` 代表 Profile.Age > 18 的条件查询。
21
22 注释后面将描述对应的 sql 语句,仅仅是描述 expr 的类似结果,并不代表实际生成的语句。
23 ```go
24 qs.Filter("id", 1) // WHERE id = 1
25 qs.Filter("profile__age", 18) // WHERE profile.age = 18
26 qs.Filter("Profile__Age", 18) // 使用字段名和Field名都是允许的
27 qs.Filter("profile__age", 18) // WHERE profile.age = 18
28 qs.Filter("profile__age__gt", 18) // WHERE profile.age > 18
29 qs.Filter("profile__age__gte", 18) // WHERE profile.age >= 18
30 qs.Filter("profile__age__in", 18, 20) // WHERE profile.age IN (18, 20)
31
32 qs.Filter("profile__age__in", 18, 20).Exclude("profile__lt", 1000)
33 // WHERE profile.age IN (18, 20) AND NOT profile_id < 1000
34 ```
35 ## Operators
36
37 当前支持的操作符号:
38
39 * [exact](#exact) / [iexact](#iexact) 等于
40 * [contains](#contains) / [icontains](#icontains) 包含
41 * [gt / gte](#gt / gte) 大于 / 大于等于
42 * [lt / lte](#lt / lte) 小于 / 小于等于
43 * [startswith](#startswith) / [istartswith](#istartswith) 以...起始
44 * [endswith](#endswith) / [iendswith](#iendswith) 以...结束
45 * [in](#in)
46 * [isnull](#isnull)
47
48 后面以 `i` 开头的表示:大小写不敏感
49
50 #### exact
51
52 Filter / Exclude / Condition expr 的默认值
53 ```go
54 qs.Filter("name", "slene") // WHERE name = 'slene'
55 qs.Filter("name__exact", "slene") // WHERE name = 'slene'
56 // 使用 = 匹配,大小写是否敏感取决于数据表使用的 collation
57 qs.Filter("profile", nil) // WHERE profile_id IS NULL
58 ```
59 #### iexact
60 ```go
61 qs.Filter("name__iexact", "slene")
62 // WHERE name LIKE 'slene'
63 // 大小写不敏感,匹配任意 'Slene' 'sLENE'
64 ```
65 #### contains
66 ```go
67 qs.Filter("name__contains", "slene")
68 // WHERE name LIKE BINARY '%slene%'
69 // 大小写敏感, 匹配包含 slene 的字符
70 ```
71 #### icontains
72 ```go
73 qs.Filter("name__icontains", "slene")
74 // WHERE name LIKE '%slene%'
75 // 大小写不敏感, 匹配任意 'im Slene', 'im sLENE'
76 ```
77 #### in
78 ```go
79 qs.Filter("profile__age__in", 17, 18, 19, 20)
80 // WHERE profile.age IN (17, 18, 19, 20)
81 ```
82 #### gt / gte
83 ```go
84 qs.Filter("profile__age__gt", 17)
85 // WHERE profile.age > 17
86
87 qs.Filter("profile__age__gte", 18)
88 // WHERE profile.age >= 18
89 ```
90 #### lt / lte
91 ```go
92 qs.Filter("profile__age__lt", 17)
93 // WHERE profile.age < 17
94
95 qs.Filter("profile__age__lte", 18)
96 // WHERE profile.age <= 18
97 ```
98 #### startswith
99 ```go
100 qs.Filter("name__startswith", "slene")
101 // WHERE name LIKE BINARY 'slene%'
102 // 大小写敏感, 匹配以 'slene' 起始的字符串
103 ```
104 #### istartswith
105 ```go
106 qs.Filter("name__istartswith", "slene")
107 // WHERE name LIKE 'slene%'
108 // 大小写不敏感, 匹配任意以 'slene', 'Slene' 起始的字符串
109 ```
110 #### endswith
111 ```go
112 qs.Filter("name__endswith", "slene")
113 // WHERE name LIKE BINARY '%slene'
114 // 大小写敏感, 匹配以 'slene' 结束的字符串
115 ```
116 #### iendswith
117 ```go
118 qs.Filter("name__startswith", "slene")
119 // WHERE name LIKE '%slene'
120 // 大小写不敏感, 匹配任意以 'slene', 'Slene' 结束的字符串
121 ```
122 #### isnull
123 ```go
124 qs.Filter("profile__isnull", true)
125 qs.Filter("profile_id__isnull", true)
126 // WHERE profile_id IS NULL
127
128 qs.Filter("profile__isnull", false)
129 // WHERE profile_id IS NOT NULL
130 ```
131 ## 高级查询接口使用
132
133 QuerySeter 是高级查询使用的接口,我们来熟悉下他的接口方法
134
135 * type QuerySeter interface {
136 * [Filter(string, ...interface{}) QuerySeter](#filter)
137 * [Exclude(string, ...interface{}) QuerySeter](#exclude)
138 * [SetCond(*Condition) QuerySeter](#setcond)
139 * [Limit(int, ...int64) QuerySeter](#limit)
140 * [Offset(int64) QuerySeter](#offset)
141 * [OrderBy(...string) QuerySeter](#orderby)
142 * [RelatedSel(...interface{}) QuerySeter](#relatedsel)
143 * [Count() (int64, error)](#count)
144 * [Update(Params) (int64, error)](#update)
145 * [Delete() (int64, error)](#delete)
146 * [PrepareInsert() (Inserter, error)](#prepareinsert)
147 * [All(interface{}) (int64, error)](#all)
148 * [One(Modeler) error](#one)
149 * [Values(*[]Params, ...string) (int64, error)](#values)
150 * [ValuesList(*[]ParamsList, ...string) (int64, error)](#valueslist)
151 * [ValuesFlat(*ParamsList, string) (int64, error)](#valuesflat)
152 * }
153
154 * 每个返回 QuerySeter 的 api 调用时都会新建一个 QuerySeter,不影响之前创建的。
155
156 * 高级查询使用 Filter 和 Exclude 来做常用的条件查询。囊括两种清晰的过滤规则:包含, 排除
157
158 #### Filter
159
160 用来过滤查询结果,起到 **包含条件** 的作用
161
162 多个 Filter 之间使用 `AND` 连接
163 ```go
164 qs.Filter("profile__isnull", true).Filter("name", "slene")
165 // WHERE profile_id IS NULL AND name = 'slene'
166 ```
167
168 #### Exclude
169
170 用来过滤查询结果,起到 **排除条件** 的作用
171
172 使用 `NOT` 排除条件
173
174 多个 Exclude 之间使用 `AND` 连接
175 ```go
176 qs.Exclude("profile__isnull", true).Filter("name", "slene")
177 // WHERE NOT profile_id IS NULL AND name = 'slene'
178 ```
179
180 #### SetCond
181
182 自定义条件表达式
183
184 ```go
185 cond := NewCondition()
186 cond1 := cond.And("profile__isnull", false).AndNot("status__in", 1).Or("profile__age__gt", 2000)
187
188 qs := orm.QueryTable("user")
189 qs = qs.SetCond(cond1)
190 // WHERE ... AND ... AND NOT ... OR ...
191
192 cond2 := cond.AndCond(cond1).OrCond(cond.And("name", "slene"))
193 qs = qs.SetCond(cond2).Count()
194 // WHERE (... AND ... AND NOT ... OR ...) OR ( ... )
195 ```
196
197 #### Limit
198
199 限制最大返回数据行数,第二个参数可以设置 `Offset`
200 ```go
201 var DefaultRowsLimit = 1000 // orm 默认的 limit 值为 1000
202
203 // 默认情况下 select 查询的最大行数为 1000
204 // LIMIT 1000
205
206 qs.Limit(10)
207 // LIMIT 10
208
209 qs.Limit(10, 20)
210 // LIMIT 10 OFFSET 20
211
212 qs.Limit(-1)
213 // no limit
214
215 qs.Limit(-1, 100)
216 // LIMIT 18446744073709551615 OFFSET 100
217 // 18446744073709551615 是 1<<64 - 1 用来指定无 limit 限制 但有 offset 偏移的情况
218 ```
219
220 #### Offset
221
222 设置 偏移行数
223 ```go
224 qs.Offset(20)
225 // LIMIT 1000 OFFSET 20
226 ```
227
228 #### OrderBy
229
230 参数使用 **expr**
231
232 在 expr 前使用减号 `-` 表示 `DESC` 的排列
233 ```go
234 qs.OrderBy("id", "-profile__age")
235 // ORDER BY id ASC, profile.age DESC
236
237 qs.OrderBy("-profile__age", "profile")
238 // ORDER BY profile.age DESC, profile_id ASC
239 ```
240
241 #### RelatedSel
242
243 关系查询,参数使用 **expr**
244 ```go
245 var DefaultRelsDepth = 5 // 默认情况下直接调用 RelatedSel 将进行最大 5 层的关系查询
246
247 qs := o.QueryTable("post")
248
249 qs.RelateSel()
250 // INNER JOIN user ... LEFT OUTER JOIN profile ...
251
252 qs.RelateSel("user")
253 // INNER JOIN user ...
254 // 设置 expr 只对设置的字段进行关系查询
255
256 // 对设置 null 属性的 Field 将使用 LEFT OUTER JOIN
257 ```
258
259 #### Count
260 依据当前的查询条件,返回结果行数
261 ```go
262 cnt, err := o.QueryTable("user").Count() // SELECT COUNT(*) FROM USER
263 fmt.Printf("Count Num: %s, %s", cnt, err)
264 ```
265
266 #### Update
267 依据当前查询条件,进行批量更新操作
268 ```go
269 num, err := o.QueryTable("user").Filter("name", "slene").Update(orm.Params{
270 "name": "astaxie",
271 })
272 fmt.Printf("Affected Num: %s, %s", num, err)
273 // SET name = "astaixe" WHERE name = "slene"
274 ```
275
276 #### Delete
277 依据当前查询条件,进行批量删除操作
278 ```go
279 num, err := o.QueryTable("user").Filter("name", "slene").Delete()
280 fmt.Printf("Affected Num: %s, %s", num, err)
281 // DELETE FROM user WHERE name = "slene"
282 ```
283
284 #### PrepareInsert
285
286 用于一次 prepare 多次 insert 插入,以提高批量插入的速度。
287
288 ```go
289 var users []*User
290 ...
291 qs := o.QueryTable("user")
292 i, _ := qs.PrepareInsert()
293 for _, user := range users {
294 id, err := i.Insert(user)
295 if err != nil {
296 ...
297 }
298 }
299 // PREPARE INSERT INTO user (`name`, ...) VALUES (?, ...)
300 // EXECUTE INSERT INTO user (`name`, ...) VALUES ("slene", ...)
301 // EXECUTE ...
302 // ...
303 i.Close() // 别忘记关闭 statement
304 ```
305
306 #### All
307 返回对应的结果集对象
308 ```go
309 var users []*User
310 num, err := o.QueryTable("user").Filter("name", "slene").All(&users)
311 fmt.Printf("Returned Rows Num: %s, %s", num, err)
312 ```
313
314 #### One
315
316 尝试返回单条记录
317
318 ```go
319 var user *User
320 err := o.QueryTable("user").Filter("name", "slene").One(&user)
321 if err == orm.ErrMultiRows {
322 // 多条的时候报错
323 fmt.Printf("Returned Multi Rows Not One")
324 }
325 if err == orm.ErrNoRows {
326 // 没有找到记录
327 fmt.Printf("Not row found")
328 }
329 ```
330
331 #### Values
332 返回结果集的 key => value 值
333
334 key 为 Model 里的 Field name,value 的值 以 string 保存
335
336 ```go
337 var maps []orm.Params
338 num, err := o.QueryTable("user").Values(&maps)
339 if err != nil {
340 fmt.Printf("Result Nums: %d\n", num)
341 for _, m := range maps {
342 fmt.Println(m["Id"], m["Name"])
343 }
344 }
345 ```
346
347 返回指定的 Field 数据
348
349 **TODO**: 暂不支持级联查询 **RelatedSel** 直接返回 Values
350
351 但可以直接指定 expr 级联返回需要的数据
352
353 ```go
354 var maps []orm.Params
355 num, err := o.QueryTable("user").Values(&maps, "id", "name", "profile", "profile__age")
356 if err != nil {
357 fmt.Printf("Result Nums: %d\n", num)
358 for _, m := range maps {
359 fmt.Println(m["Id"], m["Name"], m["Profile"], m["Profile__Age"])
360 // map 中的数据都是展开的,没有复杂的嵌套
361 }
362 }
363 ```
364
365 #### ValuesList
366
367 顾名思义,返回的结果集以slice存储
368
369 结果的排列与 Model 中定义的 Field 顺序一致
370
371 返回的每个元素值以 string 保存
372
373 ```go
374 var lists []orm.ParamsList
375 num, err := o.QueryTable("user").ValuesList(&lists)
376 if err != nil {
377 fmt.Printf("Result Nums: %d\n", num)
378 for _, row := range lists {
379 fmt.Println(row)
380 }
381 }
382 ```
383
384 当然也可以指定 expr 返回指定的 Field
385
386 ```go
387 var lists []orm.ParamsList
388 num, err := o.QueryTable("user").ValuesList(&lists, "name", "profile__age")
389 if err != nil {
390 fmt.Printf("Result Nums: %d\n", num)
391 for _, row := range lists {
392 fmt.Printf("Name: %s, Age: %s\m", row[0], row[1])
393 }
394 }
395 ```
396
397 #### ValuesFlat
398
399 只返回特定的 Field 值,讲结果集展开到单个 slice 里
400
401 ```go
402 var list orm.ParamsList
403 num, err := o.QueryTable("user").ValuesFlat(&list, "name")
404 if err != nil {
405 fmt.Printf("Result Nums: %d\n", num)
406 fmt.Printf("All User Names: %s", strings.Join(list, ", ")
407 }
408 ```
409
410
411
1 最新文档请查看 beedoc
2
3 * [中文](http://beego.me/docs/Models_Overview?lang=zh)
4 * [English](http://beego.me/docs/Models_Overview?lang=en)
5
6 ## 文档目录
7
8 1. [Orm 使用方法](Orm.md)
9 - [数据库的设置](Orm.md#数据库的设置)
10 * [驱动类型设置](Orm.md#registerdriver)
11 * [参数设置](Orm.md#registerdatabase)
12 * [时区设置](Orm.md#时区设置)
13 - [注册模型](Orm.md#注册模型)
14 - [ORM 接口使用](Orm.md#orm-接口使用)
15 - [调试模式打印查询语句](Orm.md#调试模式打印查询语句)
16 2. [对象的CRUD操作](Object.md)
17 3. [高级查询](Query.md)
18 - [使用的表达式语法](Query.md#expr)
19 - [支持的操作符号](Query.md#operators)
20 - [高级查询接口使用](Query.md#高级查询接口使用)
21 4. [使用SQL语句进行查询](Raw.md)
22 5. [事务处理](Transaction.md)
23 6. [模型定义](Models.md)
24 - [Struct Tag 设置参数](Models.md#struct-tag-设置参数)
25 - [表关系设置](Models.md#表关系设置)
26 - [模型字段与数据库类型的对应](Models.md#模型字段与数据库类型的对应)
27 7. [命令模式](Cmd.md)
28 - [自动建表](Cmd.md#自动建表)
29 - [打印建表SQL](Cmd.md#打印建表sql)
30 8. [Test ORM](Test.md)
31 9. Custom Fields
32 10. Faq
33
34
35 ### 文档更新记录
36
37 * 2013-08-20: 这里不再更新,最新文档在 beedoc, [中文](http://beego.me/docs/Models_Overview?lang=zh) / [English](http://beego.me/docs/Models_Overview?lang=en)
38 * 2013-08-19: 增加[自动建表](Cmd.md#自动建表)功能
39 * 2013-08-13: ORM 的 [时区设置](Orm.md#时区设置)
40 * 2013-08-13: [模型字段与数据库类型的对应](Models.md#模型字段与数据库类型的对应) 推荐的数据库对应使用的类型
1 ## 使用SQL语句进行查询
2
3 * 使用 Raw SQL 查询,无需使用 ORM 表定义
4 * 多数据库,都可直接使用占位符号 `?`,自动转换
5 * 查询时的参数,支持使用 Model Struct 和 Slice, Array
6
7 ```go
8 ids := []int{1, 2, 3}
9 p.Raw("SELECT name FROM user WHERE id IN (?, ?, ?)", ids)
10 ```
11
12 创建一个 **RawSeter**
13
14 ```go
15 o := NewOrm()
16 var r RawSeter
17 r = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")
18 ```
19
20 * type RawSeter interface {
21 * [Exec() (int64, error)](#exec)
22 * [QueryRow(...interface{}) error](#queryrow)
23 * [QueryRows(...interface{}) (int64, error)](#queryrows)
24 * [SetArgs(...interface{}) RawSeter](#setargs)
25 * [Values(*[]Params) (int64, error)](#values)
26 * [ValuesList(*[]ParamsList) (int64, error)](#valueslist)
27 * [ValuesFlat(*ParamsList) (int64, error)](#valuesflat)
28 * [Prepare() (RawPreparer, error)](#prepare)
29 * }
30
31 #### Exec
32
33 执行sql语句
34
35 ```go
36 num, err := r.Exec()
37 ```
38
39 #### QueryRow
40
41 TODO
42
43 #### QueryRows
44
45 TODO
46
47 #### SetArgs
48
49 改变 Raw(sql, args...) 中的 args 参数,返回一个新的 RawSeter
50
51 用于单条 sql 语句,重复利用,替换参数然后执行。
52
53 ```go
54 num, err := r.SetArgs("arg1", "arg2").Exec()
55 num, err := r.SetArgs("arg1", "arg2").Exec()
56 ...
57 ```
58 #### Values / ValuesList / ValuesFlat
59
60 Raw SQL 查询获得的结果集 Value 为 `string` 类型,NULL 字段的值为空 ``
61
62 #### Values
63
64
65 返回结果集的 key => value 值
66
67 ```go
68 var maps []orm.Params
69 num, err = o.Raw("SELECT user_name FROM user WHERE status = ?", 1).Values(&maps)
70 if err == nil && num > 0 {
71 fmt.Println(maps[0]["user_name"]) // slene
72 }
73 ```
74
75 #### ValuesList
76
77 返回结果集 slice
78
79 ```go
80 var lists []orm.ParamsList
81 num, err = o.Raw("SELECT user_name FROM user WHERE status = ?", 1).ValuesList(&lists)
82 if err == nil && num > 0 {
83 fmt.Println(lists[0][0]) // slene
84 }
85 ```
86
87 #### ValuesFlat
88
89 返回单一字段的平铺 slice 数据
90
91 ```go
92 var list orm.ParamsList
93 num, err = o.Raw("SELECT id FROM user WHERE id < ?", 10).ValuesList(&list)
94 if err == nil && num > 0 {
95 fmt.Println(list) // []{"1","2","3",...}
96 }
97 ```
98
99 #### Prepare
100
101 用于一次 prepare 多次 exec,以提高批量执行的速度。
102
103 ```go
104 p, err := o.Raw("UPDATE user SET name = ? WHERE name = ?").Prepare()
105 num, err := p.Exec("testing", "slene")
106 num, err = p.Exec("testing", "astaxie")
107 ...
108 ...
109 p.Close() // 别忘记关闭 statement
110 ```
111
112 ## FAQ
113
114 1. 我的 app 需要支持多类型数据库,如何在使用 Raw SQL 的时候判断当前使用的数据库类型。
115
116 使用 Ormer 的 [Driver方法](Orm.md#driver) 可以进行判断
1 ## Test ORM
2
3 测试代码参见
4
5 ```bash
6 models_test.go // 表定义
7 orm_test.go // 测试用例
8 ```
9
10 #### MySQL
11 ```bash
12 mysql -u root -e 'create database orm_test;'
13 export ORM_DRIVER=mysql
14 export ORM_SOURCE="root:@/orm_test?charset=utf8"
15 go test -v github.com/astaxie/beego/orm
16 ```
17
18
19 #### Sqlite3
20 ```bash
21 touch /path/to/orm_test.db
22 export ORM_DRIVER=sqlite3
23 export ORM_SOURCE=/path/to/orm_test.db
24 go test -v github.com/astaxie/beego/orm
25 ```
26
27
28 #### PostgreSQL
29 ```bash
30 psql -c 'create database orm_test;' -U postgres
31 export ORM_DRIVER=postgres
32 export ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable"
33 go test -v github.com/astaxie/beego/orm
34 ```
...\ No newline at end of file ...\ No newline at end of file
1 ## 事务处理
2
3 orm 可以简单的进行事务操作
4
5 ```go
6 o := NewOrm()
7 err := o.Begin()
8 // 事务处理过程
9 ...
10 ...
11 // 此过程中的所有使用 o Ormer 对象的查询都在事务处理范围内
12 if SomeError {
13 err = o.Rollback()
14 } else {
15 err = o.Commit()
16 }
17 ```
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!