mirror of https://github.com/go-gorm/gorm.git
Update README
This commit is contained in:
parent
e0b90d9770
commit
4e1e2a0fbb
174
README.md
174
README.md
|
@ -19,11 +19,12 @@ Yet Another ORM library for Go, aims for developer friendly
|
|||
## Conventions
|
||||
|
||||
```go
|
||||
type User struct { // TableName: `users`, gorm will pluralize struct's name as table name
|
||||
// TableName: `users`, gorm will pluralize struct's name as table name, you are possible to turn off this feature
|
||||
type User struct {
|
||||
Id int64 // Id: Database Primary key
|
||||
Birthday time.Time
|
||||
Age int64
|
||||
Name string `sql:"size:255"` // set this field's length and as not null with tag
|
||||
Name string `sql:"size:255"` // set this field's length in database
|
||||
CreatedAt time.Time // Time of record is created, will be insert automatically
|
||||
UpdatedAt time.Time // Time of record is updated, will be updated automatically
|
||||
DeletedAt time.Time // Time of record is deleted, refer `Soft Delete` for more
|
||||
|
@ -33,22 +34,22 @@ type User struct { // TableName: `users`, gorm will pluralize struct's n
|
|||
BillingAddressId sql.NullInt64 // Embedded struct BillingAddress's foreign key
|
||||
ShippingAddress Address // Embedded struct
|
||||
ShippingAddressId int64 // Embedded struct ShippingAddress's foreign key
|
||||
IgnoreMe int64 `sql:"-"` // Ignore this field with tag
|
||||
IgnoreMe int64 `sql:"-"` // Ignore this field
|
||||
}
|
||||
|
||||
type Email struct { // TableName: `emails`
|
||||
Id int64
|
||||
UserId int64 // Foreign key for above embedded structs
|
||||
Email string `sql:"type:varchar(100);"` // Set column type directly with tag
|
||||
Email string `sql:"type:varchar(100);"` // Set this field's type in database
|
||||
Subscribed bool
|
||||
}
|
||||
|
||||
type Address struct { // TableName: `addresses`
|
||||
Id int64
|
||||
Address1 string `sql:"not null;unique"` // Set column as unique with tag
|
||||
Address1 string `sql:"not null;unique"` // Set this field as not null and unique in database
|
||||
Address2 string `sql:"type:varchar(100);unique"`
|
||||
Post sql.NullString `sql:not null`
|
||||
// Be careful: "NOT NULL" will only works for NullXXX scanner, because golang will initalize a default value for most type...
|
||||
// FYI, "NOT NULL" will only works well with NullXXX Scanner, because golang will initalize a default value for most type...
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -69,20 +70,28 @@ db, err := Open("postgres", "user=gorm dbname=gorm sslmode=disable")
|
|||
db.SetPool(100)
|
||||
|
||||
|
||||
// By default, table name is plural of struct type, if you like singular table name
|
||||
// By default, table name is plural of struct type, you can use struct type as table name with:
|
||||
db.SingularTable(true)
|
||||
|
||||
|
||||
// Gorm is goroutines friendly, so you can create a global variable to keep the connection and use it everywhere like this
|
||||
// Gorm is goroutines friendly, so you can create a global variable to keep the connection and use it everywhere in your project
|
||||
// db.go
|
||||
package db
|
||||
|
||||
var DB gorm.DB
|
||||
|
||||
func init() {
|
||||
DB, err = gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable")
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Got error when connect database, the error is '%v'", err))
|
||||
}
|
||||
}
|
||||
|
||||
// user.go
|
||||
package user
|
||||
import _ "db"
|
||||
...
|
||||
DB.Save(&User{Name: "xxx"})
|
||||
...
|
||||
```
|
||||
|
||||
## Struct & Database Mapping
|
||||
|
@ -99,9 +108,9 @@ db.DropTable(User{})
|
|||
|
||||
Feel Free to update your struct, AutoMigrate will keep your database update to date.
|
||||
|
||||
FYI, AutoMigrate will only add new columns, won't change column's type or delete unused columns, to make sure gorm won't harm your data.
|
||||
FYI, AutoMigrate will only add new columns, won't change current column's type or delete unused columns, to make sure your data is safe
|
||||
|
||||
If table doesn't exist when AutoMigrate, it will run create table automatically.
|
||||
If table doesn't exist when AutoMigrate, gorm will run create table automatically.
|
||||
|
||||
(only postgres and mysql supported)
|
||||
|
||||
|
@ -118,7 +127,7 @@ db.Save(&user)
|
|||
|
||||
### Create With SubStruct
|
||||
|
||||
Refer [Query With Related](#query-with-related) to find how to find associations
|
||||
Refer [Query With Related](#query-with-related) for how to find associations
|
||||
|
||||
```go
|
||||
user := User{
|
||||
|
@ -142,32 +151,22 @@ db.Save(&user)
|
|||
// Get the first record
|
||||
db.First(&user)
|
||||
//// SELECT * FROM users ORDER BY id LIMIT 1;
|
||||
// Search table `users` are guessed from the out struct type.
|
||||
// You are possible to specify the table name with Model() if no out struct for some methods like Pluck()
|
||||
// Or set table name with Table(), if so, it will ignore the out struct even have it. more details following.
|
||||
// Search table `users` is guessed from struct's type
|
||||
|
||||
// Get the last record
|
||||
db.Last(&user)
|
||||
//// SELECT * FROM users ORDER BY id DESC LIMIT 1;
|
||||
|
||||
// Get a record without order by primary key
|
||||
db.Find(&user)
|
||||
//// SELECT * FROM users LIMIT 1;
|
||||
|
||||
// Get first record as map
|
||||
db.First(&users)
|
||||
//// SELECT * FROM users LIMIT 1;
|
||||
|
||||
// Get All records
|
||||
db.Find(&users)
|
||||
//// SELECT * FROM users;
|
||||
|
||||
// Using a Primary Key
|
||||
// Get record with primary key
|
||||
db.First(&user, 10)
|
||||
//// SELECT * FROM users WHERE id = 10;
|
||||
```
|
||||
|
||||
### Query With Where (SQL like condition)
|
||||
### Query With Where (SQL)
|
||||
|
||||
```go
|
||||
// Get the first matched record
|
||||
|
@ -205,7 +204,7 @@ db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
|
|||
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
|
||||
//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
|
||||
|
||||
// IN For Primary Key
|
||||
// IN for primary Keys
|
||||
db.Where([]int64{20, 21, 22}).Find(&users)
|
||||
//// SELECT * FROM users WHERE id IN (20, 21, 22);
|
||||
```
|
||||
|
@ -221,18 +220,18 @@ db.Not("name", "jinzhu").First(&user)
|
|||
db.Not("name", []string{"jinzhu", "jinzhu 2"}).Find(&users)
|
||||
//// SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");
|
||||
|
||||
// Not In for Primary Key
|
||||
// Not In for primary keys
|
||||
db.Not([]int64{1,2,3}).First(&user)
|
||||
//// SELECT * FROM users WHERE id NOT IN (1,2,3);
|
||||
|
||||
db.Not([]int64{}).First(&user)
|
||||
//// SELECT * FROM users;
|
||||
|
||||
// Normal SQL
|
||||
// SQL string
|
||||
db.Not("name = ?", "jinzhu").First(&user)
|
||||
//// SELECT * FROM users WHERE NOT(name = "jinzhu");
|
||||
|
||||
// Not With Struct
|
||||
// Not with struct
|
||||
db.Not(User{Name: "jinzhu"}).First(&user)
|
||||
//// SELECT * FROM users WHERE name <> "jinzhu";
|
||||
```
|
||||
|
@ -244,7 +243,7 @@ db.Not(User{Name: "jinzhu"}).First(&user)
|
|||
db.First(&user, 23)
|
||||
//// SELECT * FROM users WHERE id = 23 LIMIT 1;
|
||||
|
||||
// Normal SQL
|
||||
// SQL string
|
||||
db.Find(&user, "name = ?", "jinzhu")
|
||||
//// SELECT * FROM users WHERE name = "jinzhu";
|
||||
|
||||
|
@ -252,11 +251,11 @@ db.Find(&user, "name = ?", "jinzhu")
|
|||
db.Find(&users, "name <> ? and age > ?", "jinzhu", 20)
|
||||
//// SELECT * FROM users WHERE name <> "jinzhu" AND age > 20;
|
||||
|
||||
// Inline Search With Struct
|
||||
// Inline search with struct
|
||||
db.Find(&users, User{Age: 20})
|
||||
//// SELECT * FROM users WHERE age = 20;
|
||||
|
||||
// Inline Search With Map
|
||||
// Inline search with map
|
||||
db.Find(&users, map[string]interface{}{"age": 20})
|
||||
//// SELECT * FROM users WHERE age = 20;
|
||||
```
|
||||
|
@ -278,17 +277,17 @@ db.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "jinzhu 2"}).Find(
|
|||
### Query With Related
|
||||
|
||||
```go
|
||||
// Find emails from user with guessed foreign key
|
||||
// Find user's emails with guessed foreign key
|
||||
db.Model(&user).Related(&emails)
|
||||
//// SELECT * FROM emails WHERE user_id = 111;
|
||||
|
||||
// Find address from user with specified foreign key 'BillingAddressId'
|
||||
// Find user's billing address with specified foreign key 'BillingAddressId'
|
||||
db.Model(&user).Related(&address1, "BillingAddressId")
|
||||
//// SELECT * FROM addresses WHERE id = 123; // 123 is the value of user's BillingAddressId
|
||||
//// SELECT * FROM addresses WHERE id = 123; // 123 is user's BillingAddressId
|
||||
|
||||
// Find user from email with guessed primary key value from emails
|
||||
// Find user with guessed primary key value from email
|
||||
db.Model(&email).Related(&user)
|
||||
//// SELECT * FROM users WHERE id = 111; // 111 is the value of email's UserId
|
||||
//// SELECT * FROM users WHERE id = 111; // 111 is email's UserId
|
||||
```
|
||||
|
||||
### Query Chains
|
||||
|
@ -316,16 +315,16 @@ db.Save(&user)
|
|||
### Update one attribute with `Update`
|
||||
|
||||
```go
|
||||
// Update an existing struct's name if name is different
|
||||
// Update existing user's name if it is changed
|
||||
db.Model(&user).Update("name", "hello")
|
||||
//// UPDATE users SET name='hello' WHERE id=111;
|
||||
|
||||
// Find out a struct, and update it if name is different
|
||||
// Find out a user, and update the name if it is changed
|
||||
db.First(&user, 111).Update("name", "hello")
|
||||
//// SELECT * FROM users LIMIT 1;
|
||||
//// UPDATE users SET name='hello' WHERE id=111;
|
||||
|
||||
// Specify table name with where search
|
||||
// Update name with search condiation and specified table name
|
||||
db.Table("users").Where(10).Update("name", "hello")
|
||||
//// UPDATE users SET name='hello' WHERE id = 10;
|
||||
```
|
||||
|
@ -333,7 +332,7 @@ db.Table("users").Where(10).Update("name", "hello")
|
|||
### Update multiple attributes with `Updates`
|
||||
|
||||
```go
|
||||
// Update an existing record if have any changed values
|
||||
// Update user's name and age if they are changed
|
||||
db.Model(&user).Updates(User{Name: "hello", Age: 18})
|
||||
//// UPDATE users SET name='hello', age=18 WHERE id = 111;
|
||||
|
||||
|
@ -372,28 +371,28 @@ For those don't have the filed, will be deleted from database permanently
|
|||
db.Delete(&user)
|
||||
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
|
||||
|
||||
// Batch delete when search
|
||||
// Delete with search condiation
|
||||
db.Where("age = ?", 20).Delete(&User{})
|
||||
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
|
||||
|
||||
// For structs have DeletedAt field, when do query, will ignore deleted records by default
|
||||
// Soft deleted records will be ignored when search
|
||||
db.Where("age = 20").Find(&user)
|
||||
//// SELECT * FROM users WHERE age = 100 AND (deleted_at IS NULL AND deleted_at <= '0001-01-02');
|
||||
|
||||
// Find out all records including those deleted with Unscoped
|
||||
// Find soft deleted records with Unscoped
|
||||
db.Unscoped().Where("age = 20").Find(&users)
|
||||
//// SELECT * FROM users WHERE age = 20;
|
||||
|
||||
// Permanently delete a record with Unscoped
|
||||
// Delete record permanently with Unscoped
|
||||
db.Unscoped().Delete(&order)
|
||||
// DELETE FROM orders WHERE id=10;
|
||||
```
|
||||
|
||||
## FirstOrInit
|
||||
|
||||
Try to load the first record, if fails, initialize struct with search conditions.
|
||||
Try to get the first record, if failed, will initialize the struct with search conditions.
|
||||
|
||||
(only support map or struct conditions, SQL like conditions are not supported)
|
||||
(only support search conditions map and struct)
|
||||
|
||||
```go
|
||||
db.FirstOrInit(&user, User{Name: "non_existing"})
|
||||
|
@ -408,17 +407,17 @@ db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"})
|
|||
|
||||
### FirstOrInit With Attrs
|
||||
|
||||
Attr's arguments would be used to initialize struct if no record found, but won't be used for search
|
||||
Ignore Attrs's arguments when search, but use them to initialize the struct if no record found.
|
||||
|
||||
```go
|
||||
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
|
||||
//// SELECT * FROM USERS WHERE name = 'non_existing';
|
||||
//// User{Name: "non_existing", Age: 20}
|
||||
|
||||
// Above code could be simplified if has only one attribute
|
||||
// Or write it like this if has only one attribute
|
||||
db.Where(User{Name: "noexisting_user"}).Attrs("age", 20).FirstOrInit(&user)
|
||||
|
||||
// If a record found, Attrs would be just ignored
|
||||
// If a record found, Attrs would be ignored
|
||||
db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 30}).FirstOrInit(&user)
|
||||
//// SELECT * FROM USERS WHERE name = jinzhu';
|
||||
//// User{Id: 111, Name: "Jinzhu", Age: 20}
|
||||
|
@ -426,7 +425,7 @@ db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 30}).FirstOrInit(&user)
|
|||
|
||||
### FirstOrInit With Assign
|
||||
|
||||
Assign's arguments would be used to set the struct even a record found, but won't be used for search
|
||||
Ignore Assign's arguments when search, but use them to fill the struct regardless record found or not
|
||||
|
||||
```go
|
||||
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
|
||||
|
@ -438,7 +437,7 @@ db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 30}).FirstOrInit(&user)
|
|||
|
||||
## FirstOrCreate
|
||||
|
||||
Try to load the first record, if fails, initialize struct with search conditions and save it
|
||||
Try to get the first record, if failed, will initialize the struct with search conditions and insert it to database
|
||||
|
||||
```go
|
||||
db.FirstOrCreate(&user, User{Name: "non_existing"})
|
||||
|
@ -453,7 +452,7 @@ db.FirstOrCreate(&user, map[string]interface{}{"name": "jinzhu", "age": 30})
|
|||
|
||||
### FirstOrCreate With Attrs
|
||||
|
||||
Attr's arguments would be used to initialize struct if no record found, but won't be used for search
|
||||
Ignore Attrs's arguments when search, but use them to initialize the struct if no record found.
|
||||
|
||||
```go
|
||||
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
|
||||
|
@ -466,9 +465,7 @@ db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 30}).FirstOrCreate(&user)
|
|||
|
||||
### FirstOrCreate With Assign
|
||||
|
||||
Assign's arguments would be used to initialize the struct if not record found,
|
||||
|
||||
If any record found, will assign those values to the record, and save it back to database.
|
||||
Ignore Assign's arguments when search, but use them to fill the struct regardless record found or not, then save it back to database
|
||||
|
||||
```go
|
||||
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
|
||||
|
@ -493,6 +490,7 @@ db.Select("name, age").Find(&users)
|
|||
db.Order("age desc, name").Find(&users)
|
||||
//// SELECT * FROM users ORDER BY age desc, name;
|
||||
|
||||
// Multiple orders
|
||||
db.Order("age desc").Order("name").Find(&users)
|
||||
//// SELECT * FROM users ORDER BY age desc, name;
|
||||
|
||||
|
@ -508,7 +506,7 @@ db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
|
|||
db.Limit(3).Find(&users)
|
||||
//// SELECT * FROM users LIMIT 3;
|
||||
|
||||
// Cleanup limit with -1
|
||||
// Remove limit with -1
|
||||
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
|
||||
//// SELECT * FROM users LIMIT 10; (users1)
|
||||
//// SELECT * FROM users; (users2)
|
||||
|
@ -520,7 +518,7 @@ db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
|
|||
db.Offset(3).Find(&users)
|
||||
//// SELECT * FROM users OFFSET 3;
|
||||
|
||||
// Cleanup offset with -1
|
||||
// Remove offset with -1
|
||||
db.Offset(10).Find(&users1).Offset(-1).Find(&users2)
|
||||
//// SELECT * FROM users OFFSET 10; (users1)
|
||||
//// SELECT * FROM users; (users2)
|
||||
|
@ -565,29 +563,30 @@ db.Select("name, age").Find(&users)
|
|||
|
||||
## Callbacks
|
||||
|
||||
Callback is a function defined to a struct, the function would be run when reflect a struct to database.
|
||||
If a function return error, gorm will prevent future operations and do rollback
|
||||
Callbacks are functions defined to struct's pointer, they would be run when save a struct to database.
|
||||
If any callback return error, gorm will stop future operations and do rollback
|
||||
|
||||
Those callbacks are defined now:
|
||||
Below callbacks are supported now:
|
||||
|
||||
`BeforeCreate`, `AfterCreate`
|
||||
`BeforeUpdate`, `AfterUpdate`
|
||||
`BeforeSave`, `AfterSave`
|
||||
`BeforeDelete`, `AfterDelete`
|
||||
|
||||
For example:
|
||||
|
||||
```go
|
||||
// Won't update readonly user
|
||||
func (u *User) BeforeUpdate() (err error) {
|
||||
if u.readonly() {
|
||||
err = errors.New("Read Only User")
|
||||
err = errors.New("Read Only User!")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// If have more than 1000 users, will rollback the insertion
|
||||
// Rollback the insertion if have more than 1000 users
|
||||
func (u *User) AfterCreate() (err error) {
|
||||
if (u.Id > 1000) { // just an example, don't use Id to count users
|
||||
err = errors.New("Only 1000 users allowed")
|
||||
if (u.Id > 1000) { // Just as example, don't use Id to count users!
|
||||
err = errors.New("Only 1000 users allowed!")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -596,26 +595,20 @@ func (u *User) AfterCreate() (err error) {
|
|||
## Specify Table Name
|
||||
|
||||
```go
|
||||
// When Create Table from struct
|
||||
// Create `deleted_users` table with User's fields
|
||||
db.Table("deleted_users").CreateTable(&User{})
|
||||
|
||||
// When Pluck
|
||||
db.Table("users").Pluck("age", &ages)
|
||||
//// SELECT age FROM users;
|
||||
|
||||
// When Query
|
||||
// Search from table `deleted_users`, and fill results to []User
|
||||
var deleted_users []User
|
||||
db.Table("deleted_users").Find(&deleted_users)
|
||||
//// SELECT * FROM deleted_users;
|
||||
|
||||
// When Delete
|
||||
// Delete results from table `deleted_users` with search conditions
|
||||
db.Table("deleted_users").Where("name = ?", "jinzhu").Delete()
|
||||
//// DELETE FROM deleted_users WHERE name = 'jinzhu';
|
||||
```
|
||||
|
||||
### Specify Table Name for Struct
|
||||
|
||||
You are possible to specify table name for a struct by defining method TableName
|
||||
### Specify Table Name for Struct permanently with TableName method
|
||||
|
||||
```go
|
||||
type Cart struct {
|
||||
|
@ -664,7 +657,7 @@ db.LogMode(true)
|
|||
|
||||
```go
|
||||
// Use your own logger
|
||||
// Checkout gorm's default logger for how to format messages: https://github.com/jinzhu/gorm/blob/master/logger.go#files
|
||||
// Refer gorm's default logger for how to format messages: https://github.com/jinzhu/gorm/blob/master/logger.go#files
|
||||
db.SetLogger(log.New(os.Stdout, "\r\n", 0))
|
||||
|
||||
// Disable log
|
||||
|
@ -687,10 +680,12 @@ query := db.Where("name = ?", "jinzhu").First(&user)
|
|||
query := db.First(&user).Limit(10).Find(&users)
|
||||
//// query.Error keep the latest error happened
|
||||
//// query.Errors keep all errors happened
|
||||
//// If an error happened, gorm will stop do query, insert, update, delete
|
||||
//// If an error happened, gorm will stop following operations
|
||||
|
||||
// I often use below code to do error handling in real applicatoins
|
||||
err = db.Where("name = ?", "jinzhu").First(&user).Error
|
||||
// I often use some code like below to do error handling when writting applicatoins
|
||||
if err := db.Where("name = ?", "jinzhu").First(&user).Error; err != nil {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced Usage With Query Chain
|
||||
|
@ -700,28 +695,33 @@ Already excited about above usage? Let's see some magic!
|
|||
```go
|
||||
db.First(&first_article).Count(&total_count).Limit(10).Find(&first_page_articles).Offset(10).Find(&second_page_articles)
|
||||
//// SELECT * FROM articles LIMIT 1; (first_article)
|
||||
//// SELECT count(*) FROM articles; (count)
|
||||
//// SELECT count(*) FROM articles; (total_count)
|
||||
//// SELECT * FROM articles LIMIT 10; (first_page_articles)
|
||||
//// SELECT * FROM articles LIMIT 10 OFFSET 10; (second_page_articles)
|
||||
|
||||
|
||||
// Mix where conditions with inline conditions
|
||||
db.Where("created_at > ?", "2013-10-10").Find(&cancelled_orders, "state = ?", "cancelled").Find(&shipped_orders, "state = ?", "shipped")
|
||||
//// SELECT * FROM orders WHERE created_at > '2013/10/10' AND state = 'cancelled'; (cancelled_orders)
|
||||
//// SELECT * FROM orders WHERE created_at > '2013/10/10' AND state = 'shipped'; (shipped_orders)
|
||||
|
||||
|
||||
// Search with shared conditions from different tables
|
||||
db.Where("product_name = ?", "fancy_product").Find(&orders).Find(&shopping_carts)
|
||||
//// SELECT * FROM orders WHERE product_name = 'fancy_product'; (orders)
|
||||
//// SELECT * FROM carts WHERE product_name = 'fancy_product'; (shopping_carts)
|
||||
// Do you noticed the table is different?
|
||||
|
||||
db.Where("mail_type = ?", "TEXT").Find(&users1).Table("deleted_users").First(&user2)
|
||||
|
||||
// Search with shared conditions from different tables with specified table
|
||||
db.Where("mail_type = ?", "TEXT").Find(&users1).Table("deleted_users").Find(&users2)
|
||||
//// SELECT * FROM users WHERE mail_type = 'TEXT'; (users1)
|
||||
//// SELECT * FROM deleted_users WHERE mail_type = 'TEXT'; (users2)
|
||||
|
||||
db.Where("email = ?", "x@example.org").Attrs(User{FromIp: "111.111.111.111"}).FirstOrCreate(&user)
|
||||
//// SELECT * FROM users WHERE email = 'x@example.org';
|
||||
//// INSERT INTO "users" (email,from_ip) VALUES ("x@example.org", "111.111.111.111") (if no record found)
|
||||
|
||||
// Open your mind, add more cool examples
|
||||
// An example for how to use FirstOrCreate
|
||||
db.Where("email = ?", "x@example.org").Attrs(User{RegisteredIp: "111.111.111.111"}).FirstOrCreate(&user)
|
||||
//// SELECT * FROM users WHERE email = 'x@example.org';
|
||||
//// INSERT INTO "users" (email,registered_ip) VALUES ("x@example.org", "111.111.111.111") // if no record found
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
|
Loading…
Reference in New Issue