Примите участие в реальном бою, легко овладейте навыками добавления, удаления, изменения и запроса базы данных!
Примите участие в реальном бою, легко овладейте навыками добавления, удаления, изменения и запроса базы данных!

Примите участие в реальном бою, легко овладейте навыками добавления, удаления, изменения и запроса базы данных!

CRUD обычно относится к операциям добавления, удаления, изменения и запроса базы данных. В этой статье подробно описано, как использовать GORM для реализации операций создания, запроса, обновления и удаления.

1. Создать

Сначала определите модель и соединение с базой данных:

Язык кода:javascript
копировать
package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
	"os"
	"time"
)

type Student struct {
	gorm.Model
	Name     string
	Age      uint8
	Birthday time.Time
}

func main() {
	// Конфигурация журнала
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io Writer (цель вывода журнала, префикс и содержимое журнала - примечание переводчика)
		logger.Config{
			SlowThreshold:             time.Second, // медленный SQL порог
			LogLevel:                  logger.Info, // Уровень журнала — информация
			IgnoreRecordNotFoundError: true,        // Игнорировать ошибку ErrRecordNotFound (запись не найдена)
			Colorful:                  true,        // Цветная печать
		},
	)
	dsn := "root:123456@tcp(127.0.0.1:3306)/db1?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err) // Если в библиотеке данных нет существования, будет сообщено об ошибке.
	}
	db.AutoMigrate(&Student{})
}

1.1 Создание записей

Язык кода:javascript
копировать
	user := Student{Name: «Джарвис», Age: 18, Birthday: time.Now()}
	result := db.Create(&user)       // проходитьданныеизприходит указательсоздавать
	fmt.Println(user.ID)             // Возвращает первичный ключ вставленных данных
	fmt.Println(result.Error)        // возвращаться error
	fmt.Println(result.RowsAffected) // возвращатьсявставить записьизполоскачисло

1.2 Создание записей с указанными полями

Создает запись и обновляет данные поля.

Язык кода:javascript
копировать
	student := Student{Name: «Джарвис», Age: 19, Birthday: time.Now()}
	db.Select("Name", "Age", "CreatedAt").Create(&student)
	//  INSERT INTO `students` (`created_at`,`updated_at`,`name`,`age`) VALUES ('2024-01-10 21:05:31.507','2024-01-10 21:05:31.507','Джарвис',19)

Создает запись, а также игнорирует значения полей, переданные для пропуска.

Язык кода:javascript
копировать
	student := Student{Name: "dlrb", Age: 20, Birthday: time.Now()}
	db.Omit("Name", "Age", "CreatedAt").Create(&student)
	// INSERT INTO `students` (`updated_at`,`deleted_at`,`birthday`) VALUES ('2024-01-10 21:13:49.053',NULL,'2024-01-10 21:13:49.052')

1.3 Пакетная вставка

Чтобы эффективно вставлять большое количество записей, Воля a slice перешел к Create метод. GORM Воля генерирует один оператор SQL для вставки всех данных и обратного заполнения значения первичного ключа, крюк Метод также будет называться。

Язык кода:javascript
копировать
t, _ := time.Parse("2024-01-10", "1998-08-18")
	var student = []Student{
		{Name: «Одноклассники Сяо Ай», Birthday: t},
		{Name: «Одноклассник Сяосинь», Birthday: t},
		{Name: «Одноклассник Сяобин», Birthday: t},
		{Name: «Одноклассник Сяофан», Birthday: t},
	}
	db.Create(&student)
	for _, user := range student {
		fmt.Println(user.ID)
	}
/*
Поскольку значение даты и времени версии Mysql5.7 и выше не может быть «0000-00-00». 00:00:00',
//Метод обработки:
Изменить mysql.ini
существуют[mysqld]Добавить объект:
sql_mode=NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO
*/

использовать CreateInBatches При создании в партиях можно указать количество каждой партии, например:

Язык кода:javascript
копировать
var student [20]Student
	t, _ := time.Parse("2024-01-10", "1998-08-18")
	for i, _ := range student {
		student[i].Name = fmt.Sprintf("Число Джарвиса %d", i)
		student[i].Birthday = t
	}
	fmt.Println(student)

	db.CreateInBatches(&student, 10)

Upsert и Create With Associations Пакетная вставка также поддерживается.

Уведомление использоватьCreateBatchSize Инициализация опции GORM Когда все творение иamp; ассоциация INSERT Все Воля следуют этому варианту

Язык кода:javascript
копировать
// вставка ассоциации
д Б, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
  CreateBatchSize: 1000,
})

db := db.Session(&gorm.Session{CreateBatchSize: 1000})

users = [5000]User{{Name: "jinzhu", Pets: []Pet{pet1, pet2, pet3}}...}

db.Create(&users)
// INSERT INTO users xxx (5 batches)
// INSERT INTO pets xxx (15 batches)

1.4 Создание хуков

GORM Разрешены определяемые пользователем перехваты: BeforeSave, BeforeCreate, AfterSave, AfterCreate Создать Если вы хотите использовать метод крючка, нажмите ссылку Hooks Подробности о жизненном цикле в

Язык кода:javascript
копировать
// в основном
db.Create(&Student{
  Name:     «Джарвис»,
  Birthday: time.Now(),
})
// Вставьте предыдущую функцию крюка
func (u *Student) BeforeCreate(tx *gorm.DB) (err error) {
	fmt.Println("Студент вставлен")
	return
}

Если вы хотите пропустить крюк Методы, которые вы можете использовать SkipHooks Режим сеанса, например:

Язык кода:javascript
копировать
db.Session(&gorm.Session{SkipHooks: true}).Create(&student)

db.Session(&gorm.Session{SkipHooks: true}).Create(&student)

db.Session(&gorm.Session{SkipHooks: true}).CreateInBatches(student, 100)

1.5 Создать на основе карты

GORM поддержка на основе map[string]interface{} и []map[string]interface{}{} Создайте запись, например:

Язык кода:javascript
копировать
// Здесь нельзя указать день рождения, поскольку он имеет значение null.
db.Model(&Student{}).Create(map[string]interface{}{
  "Name": "Джарвис_001", "Age": 18,
})
// batch insert from `[]map[string]interface{}{}`
db.Model(&Student{}).Create([]map[string]interface{}{
  {"Name": "Джарвис_002", "Age": 18},
  {"Name": "Джарвис_003", "Age": 20},
})

Уведомление: в соответствии с map При создании записи ассоциация не будет вызываться, и первичный ключ не будет заполняться автоматически.

1.6 Использование выражений SQL и средства оценки контекста для создания записей (понимание)

GORM позволятьиспользовать SQL Данные вставки выражения, есть два способа достижения этой цели. в соответствии с map[string]interface{} или пользовательский тип данных Создайте, например:

Язык кода:javascript
копировать
// проходить map Создать запись
db.Model(User{}).Create(map[string]interface{}{
  "Name": "jinzhu",
  "Location": clause.Expr{SQL: "ST_PointFromText(?)", Vars: []interface{}{"POINT(100 100)"}},
})
// INSERT INTO `users` (`name`,`location`) VALUES ("jinzhu",ST_PointFromText("POINT(100 100)"));

// ввестипользовательский тип Создать запись
type Location struct {
    X, Y int
}

// Scan Метод реализован sql.Scanner интерфейс
func (loc *Location) Scan(v interface{}) error {
  // Scan a value into struct from database driver
}

func (loc Location) GormDataType() string {
  return "geometry"
}

func (loc Location) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
  return clause.Expr{
    SQL:  "ST_PointFromText(?)",
    Vars: []interface{}{fmt.Sprintf("POINT(%d %d)", loc.X, loc.Y)},
  }
}

type User struct {
  Name     string
  Location Location
}

db.Create(&User{
  Name:     "jinzhu",
  Location: Location{X: 100, Y: 100},
})
// INSERT INTO `users` (`name`,`location`) VALUES ("jinzhu",ST_PointFromText("POINT(100 100)"))

1.7 Дополнительные параметры

1.7.1 Создание ассоциации (подробнее см. об отношениях ассоциации позже)

при создании ассоциаций,не равно нулю в значении ассоциации значение, эти ассоциации будут упадок и их Hook Метод также будет называться

Язык кода:javascript
копировать
type CreditCard struct {
  gorm.Model
  Number   string
  UserID   uint
}

type User struct {
  gorm.Model
  Name       string
  CreditCard CreditCard
}

db.Create(&User{
  Name: "jinzhu",
  CreditCard: CreditCard{Number: "411111111111"}
})
// INSERT INTO `users` ...
// INSERT INTO `credit_cards` ...

Вы также можете пройти SelectOmit Пропустить объединение сохранить,Пример:

Язык кода:javascript
копировать
db.Omit("CreditCard").Create(&user)

// Пропустить все ассоциации
db.Omit(clause.Associations).Create(&user)
1.7.2 Значение по умолчанию

Вы можете использовать тег default Определите значения по умолчанию для полей, например:

Язык кода:javascript
копировать
type User struct {
  ID   int64
  Name string `gorm:"default:galeone"`
  Age  int64  `gorm:"default:18"`
}

При вставке записей в базу данных значение по умолчанию будет использоваться Значение заполнения нулевое значение поля

Уведомление Для утверждения значение по поле по умолчанию, картина 0''false ждатьнулевое значение не сохраняется в библиотеке данных. Вам нужно использовать тип указателя или Scanner/Valuer Чтобы избежать этой проблемы, например:

Язык кода:javascript
копировать
type User struct {
  gorm.Model
  Name string
  Age  *int           `gorm:"default:18"`
  Active sql.NullBool `gorm:"default:true"`
}

Уведомление Чтобы база данных имела фиктивные/сгенерированные значения по умолчанию, вы должны установить default Этикетка. Быть в Пропустить значение при миграции по Определение по умолчанию, вы можете использовать default:(-),Например:

Язык кода:javascript
копировать
type User struct {
  ID        string `gorm:"default:uuid_generate_v3()"` // db func
  FirstName string
  LastName  string
  Age       uint8
  FullName  string `gorm:"->;type:GENERATED ALWAYS AS (concat(firstname,' ',lastname));default:(-);"`
}

использоватьвиртуальный/генерироватьизценитьчас,Возможно, вам придется отключить его, создавать,возобновлять разрешения,Проверять Разрешения на уровне поля Получить подробности

1.7.3 Расстроения и конфликты (понимание)

GORM обеспечивает совместимую поддержку Upsert для различных баз данных.

иногда вставляйте данные,Сообщить о конфликте первичного ключа,иметьupsert Вы можете как обновить данные, так и вставить данные, чтобы решить эту проблему. Если первичный ключ существует, обновите его.

Язык кода:javascript
копировать
import "gorm.io/gorm/clause"

// Когда существуют конфликты, ничего не делайте
db.Clauses(clause.OnConflict{DoNothing: true}).Create(&user)

// существовать`id`В конфликте,Воля Списоквозобновлятьдлязначение по умолчанию
db.Clauses(clause.OnConflict{
  Columns:   []clause.Column{{Name: "id"}},
  DoUpdates: clause.Assignments(map[string]interface{}{"role": "user"}),
}).Create(&users)
// MERGE INTO "users" USING *** WHEN NOT MATCHED THEN INSERT *** WHEN MATCHED THEN UPDATE SET ***; SQL Server
// INSERT INTO `users` *** ON DUPLICATE KEY UPDATE ***; MySQL

// использоватьSQLзаявление
db.Clauses(clause.OnConflict{  Columns:   []clause.Column{{Name: "id"}},
  DoUpdates: clause.Assignments(map[string]interface{}{"count": gorm.Expr("GREATEST(count, VALUES(count))")}),
}).Create(&users)
// INSERT INTO `users` *** ON DUPLICATE KEY UPDATE `count`=GREATEST(count, VALUES(count));

// При конфликте существующих `id` в столбце «Воля возобновлять» указывается новое значение.
db.Clauses(clause.OnConflict{
  Columns:   []clause.Column{{Name: "id"}},
  DoUpdates: clause.AssignmentColumns([]string{"name", "age"}),
}).Create(&users)
// MERGE INTO "users" USING *** WHEN NOT MATCHED THEN INSERT *** WHEN MATCHED THEN UPDATE SET "name"="excluded"."name"; SQL Server
// INSERT INTO "users" *** ON CONFLICT ("id") DO UPDATE SET "name"="excluded"."name", "age"="excluded"."age"; PostgreSQL
// INSERT INTO `users` *** ON DUPLICATE KEY UPDATE `name`=VALUES(name),`age=VALUES(age); MySQL

// В случае существования конфликтов возобновить все столбцы, кроме первичного ключа, до новых значений ----》Это часто используется.
db.Clauses(clause.OnConflict{
  UpdateAll: true,
}).Create(&users)
// INSERT INTO "users" *** ON CONFLICT ("id") DO UPDATE SET "name"="excluded"."name", "age"="excluded"."age", ...;

Вы также можете просмотреть Расширенный запрос в FirstOrInitFirstOrCreate

Проверять Родной SQL и конструктор Получить более подробную информацию

2. Читать (запрос)

2.1 Получить один объект

GORM предоставил FirstTakeLast Метод для получения одного объекта из базы данных. При запросе к базе данных он добавляет LIMIT 1 состояние,ибезиметьоказатьсяво время записи,это Уилл возвращаться ErrRecordNotFound ошибка

Язык кода:javascript
копировать
var student Student
	// получить Первую запись (в порядке возрастания первичного ключа)
	db.First(&student)
	// SELECT * FROM users ORDER BY id LIMIT 1;

	// получить запись без обозначенного поля сортировки
	db.Take(&student)
	//SELECT * FROM users LIMIT 1;

	// получить Последнюю запись (в порядке убывания первичного ключа)
	db.Last(&student)
	// SELECT * FROM users ORDER BY id DESC LIMIT 1;
	fmt.Println(student)

	result := db.First(&student)
	fmt.Println(result.RowsAffected) // возвращатьсяоказатьсяиз Записыватьчисло
	fmt.Println(result.Error)        // returns error or nil

	// исследовать возвращатьсяизошибкаданетдабезоказаться Записыватьизошибка  ErrRecordNotFound ошибка
	fmt.Println(errors.Is(result.Error, gorm.ErrRecordNotFound))

еслиты хочешь избежатьErrRecordNotFoundошибка,ты можешьиспользоватьFind,напримерdb.Limit(1).Find(&user),Findметод приемлемstructиsliceизданные。

First и Last Уилл в соответствии Сортировка по первичному ключу соответственно Запрос первой и последней записи. только в цель struct дауказательили ВОЗпроходить db.Model() обозначение model Этот метод эффективен только тогда, когда . Дополнительно, если это актуально model Первичный ключ не определен, затем Воля нажмите model Сортировка по первому полю. Например:

Язык кода:javascript
копировать
var user User
var users []User

// works because destination struct is passed in
// работает нормально, потому что целевая структура была передана
db.First(&user)
// SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1

// works because model is specified using `db.Model()`
// использоватьmap, нужно обозначение с этой таблицей ассоциации
result := map[string]interface{}{}
db.Model(&User{}).First(&result)
// SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1

// doesn't work-->безобозначениеModel,неверный
result = map[string]interface{}{}
db.Table("users").First(&result)

// works with Take,использоватьTakeвступить в силу
result = map[string]interface{}{}
db.Table("users").Take(&result)

// no primary key defined, results will be ordered by first field (i.e., `Code`)
// Если первичного ключа нет, сортируйте по первому полю.
type Language struct {
  Code string
  Name string
}
db.First(&Language{})
// SELECT * FROM `languages` ORDER BY `languages`.`code` LIMIT 1

2.2 Поиск с использованием первичного ключа

еслипервичный ключдачислотип шрифта,Вы можете использовать в соответствиисостояние чтобы получить объект. При передаче строковых параметров требуется особая осторожность. SQL Проблема с впрыском, Проверить Безопасность Получить подробности.

Язык кода:javascript
копировать
	var user User
	var users []User
	db.First(&user, 10)
	// SELECT * FROM users WHERE id = 10;

	db.First(&user, "10")
	// SELECT * FROM users WHERE id = 10;

	db.Find(&users, []int{1,2,3})
	// SELECT * FROM users WHERE id IN (1,2,3);
	fmt.Println(user)
	fmt.Println(users)

Если первичный ключ представляет собой строку (например, например uuid),Запрос Волябыло написано так:

Язык кода:javascript
копировать
db.First(&user, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a")
// SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";

When the destination object has a primary value, the primary key will be used to build the condition, for example:

Язык кода:javascript
копировать
//Когда целевой объект имеет значение первичного ключа,первичный ключ Воляиспользуется длястроитьсостояние
var user = User{ID: 10}
db.First(&user)
// SELECT * FROM users WHERE id = 10;

var result User
db.Model(User{ID: 10}).First(&result)
// SELECT * FROM users WHERE id = 10;

2.3 Получить все объекты

Язык кода:javascript
копировать
var student []Student
// Get all records
result := db.Find(&student)
// SELECT * FROM `students` WHERE `students`.`deleted_at` IS NULL

fmt.Println(result.RowsAffected) // возвращатьсяоказатьсяиз Записыватьсчитатьчисло,ждать В“лен (студент)”
fmt.Println(result.Error) // возвращает ошибку или ноль

2.4 Условный запрос

2.4.1 Состояние строки
Язык кода:javascript
копировать
	var student Student
	// определение lastWeek и today
	lastWeek := time.Now().AddDate(0, 0, -7) // неделю назад
	today := time.Now()                      // текущее время

	// Get first matched record
	db.Where("name = ?", "Джарвис").First(&student)
	//  SELECT * FROM `students` WHERE name = 'Джарвис' AND `students`.`deleted_at` IS NULL ORDER BY `student`id` LIMIT 1

	// Get all matched records
	db.Where("name <> ?", "Джарвис").Find(&student)
	// SELECT * FROM `students` WHERE name <> 'Джарвис' AND `students`.`deleted_at` IS NULL AND `students`.` = 25

	// IN
	db.Where("name IN ?", []string{«Джарвис», "Джарвис 2"}).Find(&student)
	// SELECT * FROM `students` WHERE name IN ('Джарвис','Джарвис 2') AND `students`.`deleted_at` IS NULL ANDents`.`id` = 25

	// LIKE
	db.Where("name LIKE ?", "%Джарвис%").Find(&student)
	//  SELECT * FROM `students` WHERE name LIKE '% Джарвис%' AND `students`.`deleted_at` IS NULL AND `student`id` = 25

	// AND
	db.Where("name = ? AND age >= ?", «Джарвис», "22").Find(&student)
	// SELECT * FROM `students` WHERE (name = 'Джарвис' AND age >= '22') AND `students`.`deleted_at` IS NULLD `students`.`id` = 25

	// Time
	db.Where("updated_at > ?", lastWeek).Find(&student)
	//  SELECT * FROM `students` WHERE updated_at > '2024-01-03 23:05:18.068' AND `students`.`deleted_at` IS NULL AND `students`.`id` = 25

	// BETWEEN
	db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&student)
	//  SELECT * FROM `students` WHERE (created_at BETWEEN '2024-01-03 23:05:18.068' AND '2024-01-10 23:05:18.068') AND `students`.`deleted_at` IS NULL AND `students`.`id` = 25
2.4.2 Struct & Map состояние
Язык кода:javascript
копировать
	var student Student
	// Struct
	db.Where(&Student{Name: «Джарвис», Age: 20}).First(&student)
	// SELECT * FROM `students` WHERE `students`.`name` = 'Джарвис' AND `students`.`age` = 20 AND `students`eleted_at` IS NULL ORDER BY `students`.`id` LIMIT 1

	// Map
	db.Where(map[string]interface{}{"name": «Джарвис», "age": 20}).Find(&student)
	// SELECT * FROM `students` WHERE `age` = 20 AND `name` = 'Джарвис' AND `students`.`deleted_at` IS NULL

	// Slice of primary keys
	db.Where([]int64{20, 21, 22}).Find(&student)
	// SELECT * FROM `students` WHERE `students`.`id` IN (20,21,22) AND `students`.`deleted_at` IS NULL

NOTE When querying with struct, GORM will only query with non-zero fields, that means if your field’s value is 0, '', false or other zero values, it won’t be used to build query conditions, for example:

Язык кода:javascript
копировать
var student Student
	// При использовании структуры как Запроссостояние, gorm будет запрашивать только поля, отличные от 0, если поле равно `0`, `''`, `false` or other zero значения, это поле не использоватьсястроить Запроссостояние
	db.Where(&Student{Name: «Джарвис», Age: 0}).Find(&student)
	// SELECT * FROM `students` WHERE `students`.`name` = 'Джарвис' AND `students`.`deleted_at` IS NULL

Быть в Запроссостояние Содержитнулевое значение, canusemap, карта Воля содержит все ключевые значения как Запроссостояние,Пример:

Язык кода:javascript
копировать
	// Если вы хотите, чтобы существование Запрос содержало 0поля, вы можете сделать это с помощью usemap
	db.Where(map[string]interface{}{"Name": «Джарвис», "Age": 0}).Find(&student)
	// SELECT * FROM `students` WHERE `Age` = 0 AND `Name` = 'Джарвис' AND `students`.`deleted_at` IS NULL

For more details, see Specify Struct search fields.

2.4.3 Указание полей запроса структуры

использовать struct При поиске вы можете ввести названия полей, связанных с Волей, или dbname перешел к 'Where()' Приходитьобозначениехотетьсуществовать Запроссостояниесерединаиспользоватьизструктуравкакой конкретныйценить,Например:

Язык кода:javascript
копировать
	//существоватьиспользоватьstruct При поиске вы можете использовать имя связанного поля Воли или имя данной библиотеки, перешел к`Where(),Приходитьобозначениесуществовать Запроссостояниесерединаиспользоватьstructвкакой конкретныйценить`
	db.Where(&Student{Name: "Джарвис"}, "name", "Age").Find(&student)
	// SELECT * FROM `students` WHERE `students`.`name` = 'Джарвис' AND `students`.`age` = 0 AND `students`.leted_at` IS NULL

	db.Where(&Student{Name: "Джарвис"}, "Age").Find(&student)
	//  SELECT * FROM `students` WHERE `students`.`age` = 0 AND `students`.`deleted_at` IS NULL AND `students`.`id` = 25
2.4.4 в соответствиисостояние

Запроссостояние Это можно сделать аналогичноWhereиз Способв соответствииприезжать'First'и'Find'ждатьметодсередина

Язык кода:javascript
копировать
// Если это первичный ключ без формы, в соответствии с Первичный ключ получения записи
	db.First(&Student{}, "id = ?", "string_primary_key")
	//  SELECT * FROM `students` WHERE id = 'string_primary_key' AND `students`.`deleted_at` IS NULL ORDER BY `students`.`id` LIMIT 1

	// Plain SQL
	db.Find(&Student{}, "name = ?", "jinzhu")
	//  SELECT * FROM `students` WHERE name = 'jinzhu' AND `students`.`deleted_at` IS NULL

	db.Find(&Student{}, "name <> ? AND age > ?", "jinzhu", 20)
	//  SELECT * FROM `students` WHERE (name <> 'jinzhu' AND age > 20) AND `students`.`deleted_at` IS NULL

	// Struct
	db.Find(&Student{}, Student{Age: 20})
	// SELECT * FROM `students` WHERE `students`.`age` = 20 AND `students`.`deleted_at` IS NULL

	// Map
	db.Find(&Student{}, map[string]interface{}{"age": 20})
	// SELECT * FROM `students` WHERE `age` = 20 AND `students`.`deleted_at` IS NULL
2.4.5 Not состояние

Build NOT conditions, works similar to Where

строитьNOTсостояние,Принцип работы тот же, что и Где.

Язык кода:javascript
копировать
var student Student
	db.Not("name = ?", "Джарвис").First(&student)
	// SELECT * FROM `students` WHERE NOT name = 'Джарвис' AND `students`.`deleted_at` IS NULL ORDER BY `stuts`.`id` LIMIT 1

	// Not In
	db.Not(map[string]interface{}{"name": []string{«Джарвис», "Джарвис 2"}}).Find(&student)
	// SELECT * FROM `students` WHERE `name` NOT IN ('Джарвис','Джарвис 2') AND `students`.`deleted_at` IS NU `students`.`id` = 1

	// Struct
	db.Not(Student{Name: «Джарвис», Age: 18}).First(&student)
	// SELECT * FROM `students` WHERE (`students`.`name` <> 'Джарвис' AND `students`.`age` <> 18) AND `stude`.`deleted_at` IS NULL AND `students`.`id` = 1 ORDER BY `students`.`id` LIMIT 1

	// Not In slice of primary keys
	db.Not([]int64{1, 2, 3}).First(&student)
	// SELECT * FROM `students` WHERE `students`.`id` NOT IN (1,2,3) AND `students`.`deleted_at` IS NULL AND `students`.`id` = 1 ORDER BY `students`.`id` LIMIT 1
2.4.6 Or состояние
Язык кода:javascript
копировать
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&student)
	//  SELECT * FROM `students` WHERE (role = 'admin' OR role = 'super_admin') AND `students`.`deleted_at` IS NULL AND `students`.`id` = 4

	// Struct
	db.Where("name = 'jinzhu'").Or(Student{Name: "Джарвис 2", Age: 18}).Find(&student)
	// SELECT * FROM `students` WHERE (name = 'jinzhu' OR (`students`.`name` = 'Джарвис 2' AND `students`.`a = 18)) AND `students`.`deleted_at` IS NULL AND `students`.`id` = 4

	// Map
	db.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "Джарвис 2", "age": 18}).Find(&student)
	// SELECT * FROM `students` WHERE (name = 'jinzhu' OR (`age` = 18 AND `name` = 'Джарвис 2')) AND `studen.`deleted_at` IS NULL AND `students`.`id` = 4

For more complicated SQL queries. please also refer to Group Conditions in Advanced Query.

2.5 Выберите конкретные поля

`Select` позволяет вам отображать поля из библиотеки данных. в противном случае,GORMВоляпо умолчаниювыбиратьсклепиметь Поле

Язык кода:javascript
копировать
db.Select("name", "age").Find(&student)
// SELECT `name`,`age` FROM `students` WHERE `students`.`deleted_at` IS NULL

db.Select([]string{"name", "age"}).Find(&student)
// SELECT `name`,`age` FROM `students` WHERE `students`.`deleted_at` IS NULL

db.Table("students").Select("COALESCE(age,?)", 42).Rows()
//  SELECT COALESCE(age,42) FROM `students`

Also check out Smart Select Fields

2.6 Порядок (сортировка)

Specify order when retrieving records from the database

обозначениеотданные Библиотека Поискво время записииззаказ

Язык кода:javascript
копировать
db.Order("age desc, name").Find(&student)
	//  SELECT * FROM `students` WHERE `students`.`deleted_at` IS NULL ORDER BY age desc, name

	// Multiple orders
	db.Order("age desc").Order("name").Find(&student)
	//  SELECT * FROM `students` WHERE `students`.`deleted_at` IS NULL AND `students`.`id` = 35 ORDER BY age desc,name

	db.Clauses(clause.OrderBy{
		Expression: clause.Expr{SQL: "FIELD(id,?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true},
	}).Find(&Student{})
	// SELECT * FROM `students` WHERE `students`.`deleted_at` IS NULL ORDER BY FIELD(id,1,2,3)

2.7 Limit & Offset

Limit specify the max number of records to retrieve Offset specify the number of records to skip before starting to return the records

Limitобозначениехотеть Поискизмаксимум ЗаписыватьчислоOffsetобозначениеначинатьвозвращаться Записывать Дохотетьперепрыгнииз Записыватьчисло

Язык кода:javascript
копировать
db.Limit(3).Find(&users)
// SELECT * FROM users LIMIT 3;

// Cancel limit condition with -1
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
// SELECT * FROM users LIMIT 10; (users1)
// SELECT * FROM users; (users2)

db.Offset(3).Find(&users)
// SELECT * FROM users OFFSET 3;

db.Limit(10).Offset(5).Find(&users)
// SELECT * FROM users OFFSET 5 LIMIT 10;

// Cancel offset condition with -1
db.Offset(10).Find(&users1).Offset(-1).Find(&users2)
// SELECT * FROM users OFFSET 10; (users1)
// SELECT * FROM users; (users2)

Refer to Pagination for details on how to make a paginator

2.8 Group By & Having

Язык кода:javascript
копировать
type result struct {
  Date  time.Time
  Total int
}

db.Model(&User{}).Select("name, sum(age) as total").Where("name LIKE ?", "group%").Group("name").First(&result)
// SELECT name, sum(age) as total FROM `users` WHERE name LIKE "group%" GROUP BY `name` LIMIT 1


db.Model(&User{}).Select("name, sum(age) as total").Group("name").Having("name = ?", "group").Find(&result)
// SELECT name, sum(age) as total FROM `users` GROUP BY `name` HAVING name = "group"

rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Rows()
defer rows.Close()
for rows.Next() {
  ...
}

rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Rows()
defer rows.Close()
for rows.Next() {
  ...
}

type Result struct {
  Date  time.Time
  Total int64
}
db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Scan(&results)

2.9 Distinct

Selecting distinct values from the model

Выберите разные значения из модели

Язык кода:javascript
копировать
db.Distinct("name", "age").Order("name, age desc").Find(&results)

Distinct works with Pluck and Count too

2.10 Joins

Specify Joins conditions-обозначениесоединятьсостояние

Язык кода:javascript
копировать
type result struct {
  Name  string
  Email string
}

db.Model(&User{}).Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&result{})
// SELECT users.name, emails.email FROM `users` left join emails on emails.user_id = users.id

rows, err := db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Rows()
for rows.Next() {
  ...
}

db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results)

// multiple joins with parameter
db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Joins("JOIN credit_cards ON credit_cards.user_id = users.id").Where("credit_cards.number = ?", "411111111111").Find(&user)
Присоединяется к предварительной загрузке

You can use Joins eager loading associations with a single SQL, for example:

Можетиспользовать'Joins'Приходитьзагрузка против одиночнойSQLизассоциация

Язык кода:javascript
копировать
db.Joins("Company").Find(&users)
// SELECT `users`.`id`,`users`.`name`,`users`.`age`,`Company`.`id` AS `Company__id`,`Company`.`name` AS `Company__name` FROM `users` LEFT JOIN `companies` AS `Company` ON `users`.`company_id` = `Company`.`id`;

Join with conditions

Язык кода:javascript
копировать
db.Joins("Company", DB.Where(&Company{Alive: true})).Find(&users)
// SELECT `users`.`id`,`users`.`name`,`users`.`age`,`Company`.`id` AS `Company__id`,`Company`.`name` AS `Company__name` FROM `users` LEFT JOIN `companies` AS `Company` ON `users`.`company_id` = `Company`.`id` AND `Company`.`alive` = true;

For more details, please refer to Preloading (Eager Loading).

Joins a Derived Table

You can also use Joins to join a derived table.

Язык кода:javascript
копировать
type User struct {
    Id  int
    Age int
}

type Order struct {
    UserId     int
    FinishedAt *time.Time
}

query := db.Table("order").Select("MAX(order.finished_at) as latest").Joins("left join user user on order.user_id = user.id").Where("user.age > ?", 18).Group("order.user_id")
db.Model(&Order{}).Joins("join (?) q on order.finished_at = q.latest", query).Scan(&results)
// SELECT `order`.`user_id`,`order`.`finished_at` FROM `order` join (SELECT MAX(order.finished_at) as latest FROM `order` left join user user on order.user_id = user.id WHERE user.age > 18 GROUP BY `order`.`user_id`) q on order.finished_at = q.latest

2.11 Scan

Scanning results into a struct works similarly to the way we use Find--

Волярезультат сканирует в структуру и работает аналогично «Найти».

Язык кода:javascript
копировать
type Result struct {
  Name string
  Age  int
}

var result Result
db.Table("users").Select("name", "age").Where("name = ?", "Antonio").Scan(&result)

// Raw SQL
db.Raw("SELECT name, age FROM users WHERE name = ?", "Antonio").Scan(&result)

3. Прочтите дополнительные параметры.

3.1 Поля интеллектуального выбора

GORM разрешено пройти Select Конкретные поля выбора метода,еслитысуществоватьприложениесерединачастоиспользовать Эта функция,тытакже Можетопределениеменьшийизструктуратело,реализовать вызов API Автоматически выбирать определенные поля, например:

Язык кода:javascript
копировать
type User struct {
  ID     uint
  Name   string
  Age    int
  Gender string
  // Предположим, позже появятся сотни полей...
}

type APIUser struct {
  ID   uint
  Name string
}

// Запрос будет выбран автоматически, когда `id`, `name` Поле
db.Model(&User{}).Limit(10).Find(&APIUser{})
// SELECT `id`, `name` FROM `users` LIMIT 10

Уведомление QueryFields модель Уилл в соответствии текущий model Все имена полей select。

Язык кода:javascript
копировать
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
  QueryFields: true,
})

db.Find(&user)
// SELECT `users`.`name`, `users`.`age`, ... FROM `users` // принеси этот вариант

// Session Mode
db.Session(&gorm.Session{QueryFields: true}).Find(&user)
// SELECT `users`.`name`, `users`.`age`, ... FROM `users`

3.2 Locking (FOR UPDATE)

GORM поддерживает множество типов блокировок, таких как:

Язык кода:javascript
копировать
db.Clauses(clause.Locking{Strength: "UPDATE"}).Find(&users)
// SELECT * FROM `users` FOR UPDATE

db.Clauses(clause.Locking{
  Strength: "SHARE",
  Table: clause.Table{Name: clause.CurrentTable},
}).Find(&users)
// SELECT * FROM `users` FOR SHARE OF `users`

db.Clauses(clause.Locking{
  Strength: "UPDATE",
  Options: "NOWAIT",
}).Find(&users)
// SELECT * FROM `users` FOR UPDATE NOWAIT

Проверять Родной SQL и конструктор Получить подробности

3.3 Подзапрос

Подзапросы могут быть вложены в запросы, GORM позволятьсуществоватьиспользовать *gorm.DB Создать подзапрос, когда объект используется в качестве параметра

Язык кода:javascript
копировать
db.Where("amount > (?)", db.Table("orders").Select("AVG(amount)")).Find(&orders)
// SELECT * FROM "orders" WHERE amount > (SELECT AVG(amount) FROM "orders");

subQuery := db.Select("AVG(age)").Where("name LIKE ?", "name%").Table("users")
db.Select("AVG(age) as avgage").Group("name").Having("AVG(age) > (?)", subQuery).Find(&results)
// SELECT AVG(age) as avgage FROM `users` GROUP BY `name` HAVING AVG(age) > (SELECT AVG(age) FROM `users` WHERE name LIKE "name%")

3.4 Из подзапроса

GORM позволяет вам Table передано в метод FROM пунктиспользоватьребенок Запрос,Например:

Язык кода:javascript
копировать
db.Table("(?) as u", db.Model(&User{}).Select("name", "age")).Where("age = ?", 18).Find(&User{})
	//  SELECT * FROM (SELECT `name`,`age` FROM `users`) as u WHERE age = 18

	subQuery1 := db.Model(&User{}).Select("name")
	subQuery2 := db.Model(&Pet{}).Select("name")
	db.Table("(?) as u, (?) as p", subQuery1, subQuery2).Find(&User{})
	//  SELECT * FROM (SELECT `name` FROM `users`) as u, (SELECT `name` FROM `pets`) as p

3.5 Условия группы

использовать Group состояние облегчает написание сложного SQL

Язык кода:javascript
копировать
db.Where(
    db.Where("pizza = ?", "pepperoni").Where(db.Where("size = ?", "small").Or("size = ?", "medium")),
).Or(
    db.Where("pizza = ?", "hawaiian").Where("size = ?", "xlarge"),
).Find(&Pizza{}).Statement

// SELECT * FROM `pizzas` WHERE (pizza = "pepperoni" AND (size = "small" OR size = "medium")) OR (pizza = "hawaiian" AND size = "xlarge")

3.6 Ввод с несколькими столбцами

В запросе с несколькими столбцами

Язык кода:javascript
копировать
db.Where("(name, age, role) IN ?", [][]interface{}{{"jinzhu", 18, "admin"}, {"jinzhu2", 19, "user"}}).Find(&users)
// SELECT * FROM users WHERE (name, age, role) IN (("jinzhu", 18, "admin"), ("jinzhu 2", 19, "user"));

3.7 Именованные параметры

GORM поддерживать sql.NamedArg и map[string]interface{}{} Именованные параметры формы, например:

Язык кода:javascript
копировать
db.Where("name1 = @name OR name2 = @name", sql.Named("name", "jinzhu")).Find(&user)
// SELECT * FROM `users` WHERE name1 = "jinzhu" OR name2 = "jinzhu"

db.Where("name1 = @name OR name2 = @name", map[string]interface{}{"name": "jinzhu"}).First(&user)
// SELECT * FROM `users` WHERE name1 = "jinzhu" OR name2 = "jinzhu" ORDER BY `users`.`id` LIMIT 1

Проверять Родной SQL и конструктор Получить подробности

3.8 Найти на карте

GORM Разрешить результаты сканирования map[string]interface{} или []map[string]interface{},Не забудьте в это время обозначение Model или Table,Например:

Язык кода:javascript
копировать
result := map[string]interface{}{}
db.Model(&User{}).First(&result, "id = ?", 1)

var results []map[string]interface{}
db.Table("users").Find(&results)

3.9 FirstOrInit

получать Первыйполоскасоответствоватьиз Записывать,или ВОЗв соответствии с Инициализирует экземпляр данного состояния (только поддержка sturct и map состояние)

Язык кода:javascript
копировать
// не найдено пользователь, затем в соответствии с Инициализирует запись заданного состояния
db.FirstOrInit(&user, User{Name: "non_existing"})
// user -> User{Name: "non_existing"}

// Нашел это `name` = `jinzhu` из user
db.Where(User{Name: "jinzhu"}).FirstOrInit(&user)
// user -> User{ID: 111, Name: "Jinzhu", Age: 18}

// Нашел это `name` = `jinzhu` из user
db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"})
// user -> User{ID: 111, Name: "Jinzhu", Age: 18}

еслибезиметьоказаться Записывать,Можетиспользовать Содержит большеизсвойствоизструктурателоинициализация user,Attrs Нетбудет использоватьсягенерировать Запрос SQL

Язык кода:javascript
копировать
// не найдено пользователь, затем в соответствии с заданным изостоянием и Attrs инициализация user
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
// SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1;
// user -> User{Name: "non_existing", Age: 20}

// не найдено пользователь, затем в соответствии с заданным изостоянием и Attrs инициализация user
db.Where(User{Name: "non_existing"}).Attrs("age", 20).FirstOrInit(&user)
// SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1;
// user -> User{Name: "non_existing", Age: 20}

// Нашел это `name` = `jinzhu` из пользователь, игнорируй Attrs
db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 20}).FirstOrInit(&user)
// SELECT * FROM USERS WHERE name = jinzhu' ORDER BY id LIMIT 1;
// user -> User{ID: 111, Name: "Jinzhu", Age: 18}

несмотря наданетоказаться Записывать,Assign Атрибут Воля будет присвоен struct, но эти свойства не являются использоватьсягенерировать Запрос SQL и не будет сохранен в базе данных.

Язык кода:javascript
копировать
// не найдено user,в соответствии ссостояниеи Assign свойствоинициализация struct
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
// user -> User{Name: "non_existing", Age: 20}

// оказаться `name` = `jinzhu` из Записывать,все еще Уилл возобновлять Assign Связанныйизсвойство
db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 20}).FirstOrInit(&user)
// SELECT * FROM USERS WHERE name = jinzhu' ORDER BY id LIMIT 1;
// user -> User{ID: 111, Name: "Jinzhu", Age: 20}

3.10 FirstOrCreate

Get first matched record or create a new one with given conditions (only works with struct, map conditions), RowsAffected returns created/updated record’s count

Язык кода:javascript
копировать
// User not found, create a new record with give conditions
result := db.FirstOrCreate(&user, User{Name: "non_existing"})
// INSERT INTO "users" (name) VALUES ("non_existing");
// user -> User{ID: 112, Name: "non_existing"}
// result.RowsAffected // => 0

// Found user with `name` = `jinzhu`
result := db.Where(User{Name: "jinzhu"}).FirstOrCreate(&user)
// user -> User{ID: 111, Name: "jinzhu", "Age": 18}
// result.RowsAffected // => 0

еслибезиметьоказаться Записывать,Можетиспользовать Содержит большеизсвойствоизструктуратело Создать запись,Attrs Нетбудет использоватьсягенерировать Запрос SQL 。

Язык кода:javascript
копировать
// не найдено user,в соответствии ссостояниеи Assign свойство Создать запись
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'non_existing' ORDER BY id LIMIT 1;
// INSERT INTO "users" (name, age) VALUES ("non_existing", 20);
// user -> User{ID: 112, Name: "non_existing", Age: 20}

// Нашел это `name` = `jinzhu` из пользователь, игнорируй Attrs
db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// user -> User{ID: 111, Name: "jinzhu", Age: 18}

несмотря наданетоказаться Записывать,Assign Атрибут Воля будет присвоен struct,и Волярезультатнапиши ответданные Библиотека

Язык кода:javascript
копировать
// не найдено user,в соответствии ссостояниеи Assign свойство Создать запись
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'non_existing' ORDER BY id LIMIT 1;
// INSERT INTO "users" (name, age) VALUES ("non_existing", 20);
// user -> User{ID: 112, Name: "non_existing", Age: 20}

// Нашел это `name` = `jinzhu` из user,все еще Уилл в соответствии с Assign возобновлять Записывать
db.Where(User{Name: "jinzhu"}).Assign(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// UPDATE users SET age=20 WHERE id = 111;
// user -> User{ID: 111, Name: "jinzhu", Age: 20}

3.11 Оптимизатор, подсказки по индексу

Подсказки оптимизатора используются для управления оптимизатором запросов для выбора определенного плана выполнения запроса, GORM. проходить gorm.io/hints поставлятьподдерживать,Например:

Язык кода:javascript
копировать
import "gorm.io/hints"

db.Clauses(hints.New("MAX_EXECUTION_TIME(10000)")).Find(&User{})
// SELECT * /*+ MAX_EXECUTION_TIME(10000) */ FROM `users`

Подсказки индекса позволяют передавать подсказки индекса в базу данных в случае паники планировщика запросов.

Язык кода:javascript
копировать
import "gorm.io/hints"

db.Clauses(hints.UseIndex("idx_user_name")).Find(&User{})
// SELECT * FROM `users` USE INDEX (`idx_user_name`)

db.Clauses(hints.ForceIndex("idx_user_name", "idx_user_id").ForJoin()).Find(&User{})
// SELECT * FROM `users` FORCE INDEX FOR JOIN (`idx_user_name`,`idx_user_id`)"

ссылка Советы по оптимизатору, указатели, примечания Получить подробности

3.12 Итерация

GORM поддерживатьпроходить ХОРОШОруководить Итерировать

Язык кода:javascript
копировать
rows, err := db.Model(&User{}).Where("name = ?", "jinzhu").Rows()
defer rows.Close()

for rows.Next() {
  var user User
  // ScanRows Метод для однострочной записи Воли Сканировать в Структура
  db.ScanRows(rows, &user)

  // бизнес-логика...
}

3.13 FindInBatches

Используется для пакетного запроса и обработки записей.

Язык кода:javascript
копировать
// Каждый раз партия обрабатывается 100 полоска
result := db.Where("processed = ?", false).FindInBatches(&results, 100, func(tx *gorm.DB, batch int) error {
  for _, result := range results {
    // партияиметь дело соказатьсяиз Записывать
  }

  tx.Save(&results)

  tx.RowsAffected // На этот разпартия Операционное воздействиеиз Записыватьчисло

  batch // Batch 1, 2, 3

  // есливозвращатьсяошибка прекратит последующие операции партии
  return nil
})

result.Error // returned error
result.RowsAffected // весьпартия Операционное воздействиеиз Записыватьчисло

3.14 Перехватчик запроса

Для операций запроса GORM поддерживать AfterFind крюк, Запрос позвонит после записи, подробности по ссылке крюк

Язык кода:javascript
копировать
func (u *User) AfterFind(tx *gorm.DB) (err error) {
  if u.Role == "" {
    u.Role = "user"
  }
  return
}

3.15 Pluck

Pluck Используется для сканирования отдельного столбца из библиотеки данных Запрос и Волярезультат на срезы. Если вы хотите Запроснесколько столбцов, вам следует использовать Select и Scan

Язык кода:javascript
копировать
var ages []int64
db.Model(&users).Pluck("age", &ages)

var names []string
db.Model(&User{}).Pluck("name", &names)

db.Table("deleted_users").Pluck("name", &names)

// Distinct Pluck
db.Model(&User{}).Distinct().Pluck("Name", &names)
// SELECT DISTINCT `name` FROM `users`

// более одного Списокиз Запрос,должениспользовать `Scan` или ВОЗ `Find`,Например:
db.Select("name", "age").Scan(&users)
db.Select("name", "age").Find(&users)

3.16 Scope

Scopes позволятьтыобозначение Обычно используетсяиз Запрос,Вы можете ссылаться на эти Запросы при вызове методов.

Язык кода:javascript
копировать
func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
  return db.Where("amount > ?", 1000)
}

func PaidWithCreditCard(db *gorm.DB) *gorm.DB {
  return db.Where("pay_mode_sign = ?", "C")
}

func PaidWithCod(db *gorm.DB) *gorm.DB {
  return db.Where("pay_mode_sign = ?", "C")
}

func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
  return func (db *gorm.DB) *gorm.DB {
    return db.Where("status IN (?)", status)
  }
}

db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
// Найдите все суммы, превышающие 1000 из Заказы по кредитным картам

db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
// Найдите все суммы, превышающие 1000 заказ наложенным платежом

db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
// Найдите все суммы, превышающие 1000 и заплатилили Отправленныйиз Заказ

Проверять Scopes Получить подробности

3.17 Count

Count используется для получения количества совпадающих записей.

Язык кода:javascript
копировать
var count int64
db.Model(&User{}).Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Count(&count)
// SELECT count(1) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'

db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count)
// SELECT count(1) FROM users WHERE name = 'jinzhu'; (count)

db.Table("deleted_users").Count(&count)
// SELECT count(1) FROM deleted_users;

// Count with Distinct
db.Model(&User{}).Distinct("name").Count(&count)
// SELECT COUNT(DISTINCT(`name`)) FROM `users`

db.Table("deleted_users").Select("count(distinct(name))").Count(&count)
// SELECT count(distinct(name)) FROM deleted_users

// Count with Group
users := []User{
  {Name: "name1"},
  {Name: "name2"},
  {Name: "name3"},
  {Name: "name3"},
}

db.Model(&User{}).Group("name").Count(&count)
count // => 3

4. Обновление

4.1 Сохраните все поля

Save встречахранилищеиметьполя,Хоть Поледанулевое значение

Язык кода:javascript
копировать
	var student Student
	db.First(&student)

	student.Name = "Джарвис"
	student.Age = 100
	db.Save(&student)
	// UPDATE `students` SET `created_at`='2024-01-10 21:54:45.79',`updated_at`='2024-01-11 16:01:53.082',`deleted_at`=NULL,`name`='Джарвис',`age`=100,`birthday`='0000-00-00 00:00:00' WHERE `students`.`deleted_at` IS NULL AND ` = 1

4.2 Обновление одного столбца

когдаиспользовать Update Обновить один столбецчас,тынуждатьсяхотетьобозначениесостояние,нетно Уилл возвращаться ErrMissingWhereClause ошибка,Проверять Block Global Updates Получить подробности。когдаиспользовать Понятно Model метод, а первичный ключ объекта имеет значение, и это значение будет использоватьсястроитьсостояние,Например:

Язык кода:javascript
копировать
	var student Student
	// состояниевозобновлять(еслииметьмногополоска,Полныйвозобновлять)
	db.Model(&Student{}).Where("active = ?", true).Update("name", "jarvis")
	// UPDATE `students` SET `name`='jarvis-01',`updated_at`='2024-01-11 16:17:39.741' WHERE `students`.`deleted_at` IS NULL AND `id` = 1;

	// User из ID да `1`
	db.First(&student)
	db.Model(&student).Update("name", "jarvis-01")
	// SELECT * FROM `students` WHERE `students`.`deleted_at` IS NULL AND `students`.`id` = 1 ORDER BY `students`.`id` LIMIT 1;

	// в соответствии ссостояниеи model изценитьруководитьвозобновлять
	db.First(&student)
	db.Model(&student).Where("active = ?", true).Update("name", "jarvis-02")
	// UPDATE `students` SET `name`='jarvis-02',`updated_at`='2024-01-11 16:17:39.746' WHERE active = true AND `students`.`deleted_at` IS NULL AND `id` = 1;

4.3 Обновление нескольких столбцов

Updates методподдерживать struct и map[string]interface{} женьшеньчисло。когдаиспользовать struct При обновлении по умолчанию GORM Только Уилл возобновлять Нетнулевое значениеполя

Язык кода:javascript
копировать
//в соответствии с `struct` возобновлятьсвойство,Только Уилл возобновлять Нетнулевое значениеполя
	db.First(&student)
	db.Model(&student).Updates(Student{Name: "hello", Age: 99, Active: false})
	//SELECT * FROM `students` WHERE `students`.`deleted_at` IS NULL AND `students`.`id` = 1 ORDER BY `students`.`id` LIMIT 1;

	//в соответствии с `map` возобновлятьсвойство
	db.First(&student)
	db.Model(&student).Updates(map[string]interface{}{"name": «Губка Боб», "age": 88, "active": false})
	//UPDATE `students` SET `active`=false,`age`=88,`name`='Губка Боб Квадратные Штаны',`updated_at`='2024-01-11 16:39:56.28HERE `students`.`deleted_at` IS NULL AND `id` = 1

Уведомление когдапроходить struct При обновлении GORM Будут обновлены только ненулевые поля. еслитыхочу убедитьсяобозначение Полеодеяловозобновлять,тыдолжениспользовать Select возобновлятьвыбрано Поле,илииспользовать map для завершения операции обновления

4.4 Обновить выбранные поля

еслитыдуматьхотетьсуществоватьвозобновлятьчасвыбрано、игнорировать некоторые Поле,Вы можете использовать SelectOmit

Язык кода:javascript
копировать
// использовать Map руководить Select
	// Student's ID is `111`:
	db.First(&student)
	// Тольковозобновлятьname
	db.Model(&student).Select("name").Updates(map[string]interface{}{"name": "jarvis_002", "age": 66, "active": false})
	// UPDATE `students` SET `name`='jarvis_002',`updated_at`='2024-01-11 17:10:53.649' WHERE `students`.`deleted_at` IS NULL AND `id` = 1

	db.First(&student)
	// Все, кроме имени, возобновлено.
	db.Model(&student).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": true})
	// UPDATE `students` SET `active`=true,`age`=18,`updated_at`='2024-01-11 17:10:53.654' WHERE `students`.`deleted_at` IS NULL AND `id` = 1;

	// использовать Struct руководить Выберите (будет select нулевое значениеполя),нулевое значение Полетакже Уилл возобновлять
	// Уведомление userизidНетспособныйдля0
	db.First(&student)
	db.Model(&student).Select("Name", "Age").Updates(Student{Name: "new_name", Age: 0})
	// UPDATE `students` SET `updated_at`='2024-01-11 17:10:53.658',`name`='new_name',`age`=0 WHERE `students`.`deleted_at` IS NULL AND `id` = 1

	// Select Местоиметь Поле(Запросвключатьнулевое значение Полеиз Местоиметь Поле)
	db.First(&student)
	fmt.Println(student)
	db.Model(&student).Select("*").Updates(Student{Name: "jarvis_004", Birthday: time.Now(), Age: 33, Active: false, Model: gorm.Model{ID: 3, CreatedAt: time.Now(), UpdatedAt: time.Now()}})

	// Select удалять "CreatedAt","birthday"снаружииз Местоиметь Поле(включатьнулевое значение Полеиз Местоиметь Поле),Идентификатор уведомления станет 0
	db.Model(&student).Select("*").Omit("CreatedAt", "birthday").Updates(Student{Name: "zhuliang", Age: 0})

4.5 Обновление хука

Для операций обновления GORM поддерживать BeforeSaveBeforeUpdateAfterSaveAfterUpdate крюк, эти методы Волясуществоватьвозобновлять при записи вызываются, подробнее см. крюк

Язык кода:javascript
копировать
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
    if u.Role == "admin" {
        return errors.New("admin user not allowed to update")
    }
    return
}
// тест
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
	fmt.Println("Изменено")
	return
}

4.6 Пакетное обновление

4.6.1 Пакетное обновление

еслитыеще нетпроходить Model обозначение Записыватьизпервичный ключ,но GORM Пакетные обновления будут выполняться

Язык кода:javascript
копировать
// в соответствии с struct возобновлять--->партиявозобновлять Нетспособный用Hook
db.Model(&student).Where("active = ?", true).Updates(Student{Name: "hello", Age: 18})
// UPDATE `students` SET `updated_at`='2024-01-11 17:28:11.236',`name`='hello',`age`=18 WHERE active = true AND `students`.`deleted_at` IS NULL

// в соответствии с map возобновлять
db.Table("students").Where("id IN ?", []int{1, 2}).Updates(map[string]interface{}{"name": "jiajia_009", "age": 99})
// UPDATE `students` SET `age`=99,`name`='jiajia_009' WHERE id IN (1,2)
4.6.2 Запретить глобальные обновления

еслисуществоватьбезиметьлюбойсостояниеизвыполнить при обстоятельствах ХОРОШОпартиявозобновлять,По умолчанию,GORM не выполняет операцию и возвращает ErrMissingWhereClause ошибка

В этом отношении,Вам нужно добавить немного состояния,или ВОЗиспользовать Родной SQL или включен AllowGlobalUpdate режим, например:

Язык кода:javascript
копировать
db.Model(&User{}).Update("name", "jinzhu").Error //Сообщить об ошибке gorm.ErrMissingWhereClause

db.Model(&User{}).Where("1 = 1").Update("name", "jinzhu") //Может
// UPDATE users SET `name` = "jinzhu" WHERE 1=1


// Способ 1. Непосредственно выполните Роднойsql для глобального возобновления.
db.Exec("UPDATE users SET name = ?", "jinzhu")
// UPDATE users SET name = "jinzhu"

// Способ 2:использоватьsession
db.Session(&gorm.Session{AllowGlobalUpdate: true}).Model(&Student{}).Update("name", "Джарвис_010")
// UPDATE `students` SET `name`='Джарвис_010',`updated_at`='2024-01-11 19:12:42.408' WHERE `students`.`eted_at` IS NULL
4.6.3 Количество обновленных записей

Получить количество строк, затронутых обновлением

Язык кода:javascript
копировать
// проходить `RowsAffected` получатьвозобновлятьиз Записыватьчисло
result := db.Model(User{}).Where("active = ?", true).Updates(User{Name: "hello", Age: 18})
fmt.Println(result.RowsAffected) // возобновлятьиз Записыватьчисло
fmt.Println(result.Error) // ошибка

5. Обновите дополнительные параметры (понятно)

5.1 Обновление с использованием выражений SQL

GORM позволятьиспользовать SQL Выражения обновляют столбцы, например:

Язык кода:javascript
копировать
// user из ID да `1`
	db.First(&student)
	db.Model(&student).Update("age", gorm.Expr("age * ? + ?", 2, 100))
	// UPDATE `students` SET `age`=age * 2 + 100,`updated_at`='2024-01-11 19:29:40.712' WHERE `students`.`deleted_at` IS NULL

	db.First(&student)
	db.Model(&student).Updates(map[string]interface{}{"age": gorm.Expr("age - ? + ?", 2, 100)})
	//  UPDATE `students` SET `age`=age - 2 + 100,`updated_at`='2024-01-11 19:29:40.713' WHERE `students`.`deleted_at` IS NULL

	db.First(&student)
	db.Model(&student).UpdateColumn("age", gorm.Expr("age - ?", 10))
	//  UPDATE `students` SET `age`=age - 10 WHERE `students`.`deleted_at` IS NULL

	db.First(&student)
	db.Model(&student).Where("age > 100").UpdateColumn("age", gorm.Expr("age - ?", 100))
	//  UPDATE `students` SET `age`=age - 100 WHERE age > 100 AND `students`.`deleted_at` IS NULL

и GORM также позволяет использовать выражения SQL.、пользовательский тип данныхиз Context Valuer для обновления, например:

Язык кода:javascript
копировать
// в соответствии спользовательский тип данныхсоздавать
type Location struct {
    X, Y int
}

func (loc Location) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
  return clause.Expr{
    SQL:  "ST_PointFromText(?)",
    Vars: []interface{}{fmt.Sprintf("POINT(%d %d)", loc.X, loc.Y)},
  }
}

db.Model(&User{ID: 1}).Updates(User{
  Name:  "jinzhu",
  Location: Location{X: 100, Y: 100},
})
// UPDATE `user_with_points` SET `name`="jinzhu",`location`=ST_PointFromText("POINT(100 100)") WHERE `id` = 1

5.2 Обновление на основе подзапроса

использоватьребенок Запросвозобновлятьповерхность

Язык кода:javascript
копировать
db.Model(&user).Update("company_name", db.Model(&Company{}).Select("name").Where("companies.id = users.company_id"))
// UPDATE "users" SET "company_name" = (SELECT name FROM companies WHERE companies.id = users.company_id);

db.Table("users as u").Where("name = ?", "jinzhu").Update("company_name", db.Table("companies as c").Select("name").Where("c.id = u.company_id"))
//UPDATE users as u SET `company_name`=(SELECT name FROM companies as c WHERE c.id = u.company_id) WHERE name = 'jinzhu'



db.Table("users as u").Where("name = ?", "jinzhu").Updates(map[string]interface{}{"company_name": db.Table("companies as c").Select("name").Where("c.id = u.company_id")})
//UPDATE users as u SET `company_name`=(SELECT name FROM companies as c WHERE c.id = u.company_id) WHERE name = 'jinzhu'

5.3 Не использовать хуки и учет времени

Если вы хотите пропустить обновление Hook Метод, не отслеживающий время возобновления, можно использовать UpdateColumnUpdateColumns,Его использование аналогично UpdateUpdates

Язык кода:javascript
копировать
// Обновить один столбец
db.Model(&user).UpdateColumn("name", "hello")
// UPDATE users SET name='hello' WHERE id = 111;

// возобновить несколько столбцов
db.Model(&user).UpdateColumns(User{Name: "hello", Age: 18})
// UPDATE users SET name='hello', age=18 WHERE id = 111;

// возобновлятьвыбиратьв Список
db.Model(&user).Select("name", "age").UpdateColumns(User{Name: "hello", Age: 0})
// UPDATE users SET name='hello', age=0 WHERE id = 111;

5.4 возвращаться Исправлять ХОРОШОизданные(Понятноразвязать->mysqlНетподдерживать)

возвращатьсяодеяло Исправлятьизданные,толькоподходящийиспользуется дляподдерживать Returning база данных, например:

Язык кода:javascript
копировать
// возвращаться Местоиметь Список
var users []User
DB.Model(&users).Clauses(clause.Returning{}).Where("role = ?", "admin").Update("salary", gorm.Expr("salary * ?", 2))
// UPDATE `users` SET `salary`=salary * 2,`updated_at`="2021-10-28 17:37:23.19" WHERE role = "admin" RETURNING *
// users => []User{{ID: 1, Name: "jinzhu", Role: "admin", Salary: 100}, {ID: 2, Name: "jinzhu.2", Role: "admin", Salary: 1000}}

// возвращатьсяобозначениеиз Список
DB.Model(&users).Clauses(clause.Returning{Columns: []clause.Column{{Name: "name"}, {Name: "salary"}}}).Where("role = ?", "admin").Update("salary", gorm.Expr("salary * ?", 2))
// UPDATE `users` SET `salary`=salary * 2,`updated_at`="2021-10-28 17:37:23.19" WHERE role = "admin" RETURNING `name`, `salary`
// users => []User{{ID: 0, Name: "jinzhu", Role: "", Salary: 100}, {ID: 0, Name: "jinzhu.2", Role: "", Salary: 1000}}

5.5 Проверьте, изменились ли поля?

GORM предоставил Changed метод, который можно использовать в Before Update Hook Здесь он вернет логическое значение того, изменилось ли поле.

Changed Методы можно использовать только с UpdateUpdates метод Вместеиспользовать,иэто Толькодаисследовать Model Значение поля объекта такое же, как UpdateUpdates Равны ли значения, если значение изменилось и поле не было проигнорировано, оно будет возвращено true

Язык кода:javascript
копировать
func (u *Student) BeforeUpdate(tx *gorm.DB) (err error) {
	// если age Полеиметьизменять,не разрешено,Сообщите об ошибке напрямую
	if tx.Statement.Changed("age") {
		fmt.Println("xx")
		return errors.New("age not allowed to change")
	}
	// если Name Полеиметьизменять,изменить возрастдля18
	if tx.Statement.Changed("Name") {
		tx.Statement.SetColumn("age", 18)
	}

	// еслипроизвольный Полеиметьизменять,ИсправлятьCreatedAtчасмежду
	if tx.Statement.Changed() {
		tx.Statement.SetColumn("CreatedAt", time.Now())

	}
	return nil
}


//Изменяем имя и изменяем возраст Установить на 18
db.Model(&Student{Model: gorm.Model{ID: 1}, Name: "Джарвис"}).Updates(map[string]interface{}{"name": "Джарвис_001"})

// имя Исправлять,нодаимя其实ибезиметь Изменять,таквозраст Нетвстречаодеяло Исправлять
db.Model(&Student{Model: gorm.Model{ID: 1}, Name: "Джарвис_001"}).Updates(map[string]interface{}{"name": "Джарвис_002"})

//Изменяем имя и изменяем возраст Установить на 18
db.Model(&Student{Model: gorm.Model{ID: 1}, Name: "Джарвис_002"}).Updates(Student{Name: "Джарвис_01"})

//имя Исправлять,нодаимя其实ибезиметь Изменять,таквозраст Нетвстречаодеяло Исправлять
db.Model(&Student{Model: gorm.Model{ID: 1}, Name: "Джарвис_01"}).Updates(Student{Name: "Джарвис_02"})

// Изменение возраста не допускается.
db.Model(&Student{}).Where("id=?", 1).Updates(map[string]interface{}{"age": 100})

//произвольный Полеиметьизменять,возобновлятьCreatedAtчасмежду
db.Model(&Student{}).Where("id=?", 1).Updates(map[string]interface{}{"active": false})

5.6 Изменение значений во время обновления

Быть в Before крюксередина改Изменятьхотетьвозобновлятьизценить,еслиэтодаполныйизвозобновлять,Можетиспользовать Save;нетно,должениспользовать SetColumn ,Например:

Язык кода:javascript
копировать
func (student *Student) BeforeSave(tx *gorm.DB) (err error) {
	if pw, err := bcrypt.GenerateFromPassword(student.Password, 0); err == nil {
		tx.Statement.SetColumn("EncryptedPassword", pw)
	}

	if tx.Statement.Changed("Code") {
		student.Age += 20
		tx.Statement.SetColumn("Age", student.Age)
	}
	return nil
}

db.Model(&student).Update("Name", "jinzhu")
db.First(&student)
db.Model(&student).Update("Name", "Джарвис_010")

// Просто возобновить имя, зашифровать имя
func (student *Student) BeforeSave(tx *gorm.DB) (err error) {
	if genName, err := bcrypt.GenerateFromPassword([]byte(student.Name), 0); err == nil {
		tx.Statement.SetColumn("name", genName)
	}
	return nil
}

6. Обновление не может обновить нулевое значение.

Язык кода:javascript
копировать
	db.First(&student)
	db.Model(&student).Where("id=?", 1).Updates(Student{Name: "", Code: 200}) // тольковозобновлять Нетнулевое значение Поле
	// UPDATE `students` SET `updated_at`='2024-01-11 20:02:28.633',`code`=200 WHERE id=1 AND `students`.`deleted_at` IS NULL
	// можно увидетьNameПоле Нет Уилл возобновлять,Это разумно,потому чтодляеслинулевое значение Полетакжевозобновлять,Многие данные в таблице учеников будут пустыми при возобновлении.

6.1 Обновление с использованием sql.NullString

Язык кода:javascript
копировать
//Модель таблицы изменена на
type Student struct {
	gorm.Model
	Name sql.NullString
	Age  uint8
	Code int64
}

// Измените выражение на
db.Model(&student).Where("id=?", 1).Updates(Student{Code: 200, Name: sql.NullString{"", true}})
// можно увидеть name Полетакжевозобновлять Понятно,этотдапотому чтодля sql.NullString{"", true} встречаодеялораспознаватьдляда Нетнулевое значение,Итак, Уилл возобновлять
//UPDATE `students` SET `updated_at`='2024-01-11 20:07:10.218',`name`='',`code`=200 WHERE id=1 AND `students`.`deleted_at` IS NULL

6.2 Используйте указатели для решения

Язык кода:javascript
копировать
// Модель таблицы изменена на
type Student struct {
	gorm.Model
	Name *string
	Age  uint8
	Code int64
}

// Измените выражение на
db.First(&student)
var empty = ""
db.Model(&student).Updates(Student{Code: 200, Name: &empty}) // тольковозобновлять Нетнулевое значение Поле
// Могу назвать Полевозобновлять Понятно,этотдапотому чтодля name Поледауказательтип,указательтипизнулевое значениеда nil,таквстречаодеялораспознаватьдляда Нетнулевое значение,Итак, Уилл возобновлять
// UPDATE `students` SET `updated_at`='2024-01-11 20:10:56.543',`name`='',`code`=200 WHERE `students`.`deleted_at` IS NULL

Лично я считаю, что в повседневной разработке на Go, если у вас есть сомнения, просто используйте указатели, и в этом нет ничего плохого.

7. Удалить

7.1 Удаление записи

Удалить записьчас,удалитьудалятьобъектнуждатьсяхотетьобозначениепервичный ключ,нетновстречакурок партия Delete,Например:

Язык кода:javascript
копировать
// student из ID да `1`--->мягкое удаление
db.First(&student)
db.Delete(&student)
// UPDATE `students` SET `deleted_at`='2024-01-11 21:08:14.107' WHERE `students`.`deleted_at` IS NULL

// со лбомснаружисостояниеизудалитьудалять
db.First(&student)
db.Where("id = ?", "1").Delete(&student)
// UPDATE `students` SET `deleted_at`='2024-01-11 21:10:48.182' WHERE id = '1' AND `students`.`deleted_at` IS NULL

7.2 Удаление на основе первичного ключа

GORM разрешено пройтипервичный ключ(Можетдасложныйпервичный ключ)ив соответствиисостояние Приходитьудалитьудалятьобъект,это Можетиспользоватьчисло Характер(Например, следующий примерребенок。также Можетиспользоватьнить——переводить ВОЗПримечание)。Проверять Запрос-в соответствиисостояние(Query Inline Conditions) Узнать больше.

Язык кода:javascript
копировать
// Сначала вставьте
	var student = Student{Name: «Большой-большой волк», Age: 99}
	db.Create(&student)

	db.Delete(&student, 3)

	db.Delete(&student, "10")

	db.Delete(&student, []int{0, 1, 2})

7.3 Delete Hook

Для операций удаления GORM поддерживать BeforeDeleteAfterDelete Hook,существоватьудалитьудалятьво время записивстречавызовэтотнекоторыйметод,Проверять Hook Получить подробности

Язык кода:javascript
копировать
func (s *Student) BeforeDelete(tx *gorm.DB) (err error) {
	if s.Role == "admin" {
		return errors.New("admin student not allowed to delete")
	}
	return
}

7.4 Удаление пакета

еслиобозначениеизценить Нетвключатьхозяинсвойство,Так GORM встреча Выполнять ХОРОШОпартияудалитьудалять,это Воляудалитьудалять Местоиметьсоответствоватьиз Записывать

Язык кода:javascript
копировать
	db.Where("name LIKE ?", «%Большой-Большой Волк%»).Delete(&student)

	db.Delete(&student, "name LIKE ?", «%Большой-Большой Волк%»)
Запретить глобальное удаление

еслисуществоватьбезиметьлюбойсостояниеизвыполнить при обстоятельствах ХОРОШОпартияудалитьудалять,GORM не выполняет операцию и возвращает ErrMissingWhereClauseошибка

В этом отношении,Вам нужно добавить немного состояния,или ВОЗиспользовать Родной SQL или включен AllowGlobalUpdate режим, например:

Язык кода:javascript
копировать
//db.Delete(&student).Error // gorm.ErrMissingWhereClause

db.Where("1 = 1").Delete(&student)
// DELETE FROM `students` WHERE 1=1

db.Exec("DELETE FROM students")
// DELETE FROM students

db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&student)
// DELETE FROM students
Возвращать данные удаленных строк (понятно)

возвращатьсяодеялоудалитьудалятьизданные,толькоподходящийиспользуется дляподдерживать Returning база данных, например:

Язык кода:javascript
копировать
// возвращаться Местоиметь Список
var student []Student
db.Clauses(clause.Returning{}).Where("role = ?", "admin").Delete(&student)
// DELETE FROM `students` WHERE role = "admin" RETURNING *
// students => []User{{ID: 1, Name: "jinzhu", Role: "admin", Salary: 100}, {ID: 2, Name: "jinzhu.2", Role: "admin", Salary: 1000}}

// возвращатьсяобозначениеиз Список
db.Clauses(clause.Returning{Columns: []clause.Column{{Name: "name"}, {Name: "salary"}}}).Where("role = ?", "admin").Delete(&student)
// DELETE FROM `students` WHERE role = "admin" RETURNING `name`, `salary`
// students => []User{{ID: 0, Name: "jinzhu", Role: "", Salary: 100}, {ID: 0, Name: "jinzhu.2", Role: "", Salary: 1000}}

7.5 Мягкое удаление

Если ваша модель содержит gorm.deletedat Поле(gorm.Model Уже включено Понятно Должен Поле),это Воляавтоматически полученомягкое удалениеизспособность!

Модельные звонки с возможностью мягкого удаления Delete , запись не будет сохранена в базе данных. но GORM встреча Воля DeletedAt Установите текущее время, иты Нетспособный再проходитьобычноиз Запросметодоказаться Должен Записывать。

Язык кода:javascript
копировать
// user из ID да `111`
db.Delete(&user)
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;

// партияудалитьудалять
db.Where("age = ?", 20).Delete(&User{})
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;

// существовать Запросчасвстречапренебрегатьодеяломягкое удалениеиз Записывать
db.Where("age = 20").Find(&user)
// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;

Если вы не хотите знакомиться gorm.Model,Вы также можете включить функцию мягкого удаления следующим образом:

Язык кода:javascript
копировать
type Student struct {
  ID      int
  Deleted gorm.DeletedAt
  Name    string
}
Найти обратимо удаленные записи

Вы можете использовать Unscoped Найти обратимо удаленные записи

Язык кода:javascript
копировать
	var student []Student
	db.Unscoped().Where("name = Джарвис").Find(&student)
	fmt.Println(student)
Удалить навсегда

Вы также можете использовать Unscoped Удалить навсегдасоответствоватьиз Записывать

Язык кода:javascript
копировать
	var student []Student
	db.Unscoped().Where("id = 38").Find(&student)
	db.Unscoped().Delete(&student)
Delete Flag

Воля unix временная метка как delete flag

Язык кода:javascript
копировать
// go get -u gorm.io/plugin/soft_delete
//db.AutoMigrate(&User2{})
import "gorm.io/plugin/soft_delete"

type User2 struct {
  ID        uint
  Name      string
  DeletedAt soft_delete.DeletedAt
}

// создавать
var user2 User2=User2{Name: «Одноклассник Сяосинь»}
db.Create(&user2)
// удалитьудалять
db.Delete(&user2)

// Запрос
SELECT * FROM users WHERE deleted_at = 0;

// удалитьудалять
UPDATE users SET deleted_at = /* current unix second */ WHERE ID = 1;

INFO Сотрудничество unique Полеиспользоватьмягкое удалить, когда вам нужноиспользовать это основано на unix с отметкой времени DeletedAt Полесоздавать сводный индекс,Например: import "gorm.io/plugin/soft_delete" type User struct { ID uint Name string `gorm:"uniqueIndex:udx_name"` DeletedAt soft_delete.DeletedAt `gorm:"uniqueIndex:udx_name"` }

использовать 1 / 0 как delete flag

Язык кода:javascript
копировать
import "gorm.io/plugin/soft_delete"

type User struct {
  ID    uint
  Name  string
  IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"`
}

// Запрос
SELECT * FROM users WHERE is_del = 0;

// удалитьудалять
UPDATE users SET is_del = 1 WHERE ID = 1;

8. SQL-конструктор

8.1 Собственный SQL

Родной Запрос SQL и Scan

Язык кода:javascript
копировать
type User3 struct {
	ID   int
	Name string
	Age  int
}

// создаватьповерхность
db.AutoMigrate(&User3{})
// вставлятьданные
var student = []User3{
  {Name: «Одноклассники Сяо Ай», Age: 12},
  {Name: «Одноклассник Сяосинь», Age: 13},
  {Name: «Одноклассник Сяобин», Age: 18},
  {Name: «Одноклассник Сяофан», Age: 192},
}
db.Create(&student)
for _, user := range student {
  fmt.Println(user.ID)
}

var user User3
db.Raw("SELECT id, name, age FROM user3 WHERE name = ?",«Одноклассник Сяосинь»).Scan(&user)
fmt.Println(user)

var age int
db.Raw("SELECT SUM(age) FROM user3 WHERE name like ?", "%Одноклассник Сяосинь%").Scan(&age)
fmt.Println(age)

var users []User3
db.Raw("SELECT * FROM user3 WHERE id > ?", 0).Scan(&users)
fmt.Println(users)


// mysql Нетподдерживать
var users []User3
db.Raw("UPDATE user3 SET name = ? WHERE age = ? RETURNING id, name", «Одноклассник Сяосинь», 12).Scan(&users)
fmt.Println(users)

Exec Родной SQL

Язык кода:javascript
копировать
db.Exec("DROP TABLE users")
db.Exec("UPDATE orders SET shipped_at = ? WHERE id IN ?", time.Now(), []int64{1, 2, 3})

// Exec with SQL Expression
db.Exec("UPDATE users SET money = ? WHERE name = ?", gorm.Expr("money * ? + ?", 10000, 1), "jinzhu")

Уведомление GORM Разрешить предварительную компиляцию кэша SQL заявление Приходитьулучшатьпроизводительность,Проверять производительность Получить подробности

8.2 Именованные параметры

GORM поддерживать sql.NamedArgmap[string]interface{}{} или struct Именованные параметры формы, например:

Язык кода:javascript
копировать
// тест
var user []User3
db.Where("name = @name OR age = @age", sql.Named("name", «Одноклассник Сяосинь»), sql.Named("age", "12")).Find(&user)
fmt.Println(user)

var users []User3
db.Where("name = @name OR age = @age", sql.Named("name", «Одноклассник Сяосинь»), sql.Named("age", "12")).Find(&users)
fmt.Println(users)

// То же, что и другие
db.Where("name1 = @name OR name2 = @name", map[string]interface{}{"name": "jinzhu2"}).First(&result3)
// SELECT * FROM `users` WHERE name1 = "jinzhu2" OR name2 = "jinzhu2" ORDER BY `users`.`id` LIMIT 1

// Родной SQL иименованные параметры
db.Raw("SELECT * FROM users WHERE name1 = @name OR name2 = @name2 OR name3 = @name",
       sql.Named("name", "jinzhu1"), sql.Named("name2", "jinzhu2")).Find(&user)
// SELECT * FROM users WHERE name1 = "jinzhu1" OR name2 = "jinzhu2" OR name3 = "jinzhu1"

db.Exec("UPDATE users SET name1 = @name, name2 = @name2, name3 = @name",
        sql.Named("name", "jinzhunew"), sql.Named("name2", "jinzhunew2"))
// UPDATE users SET name1 = "jinzhunew", name2 = "jinzhunew2", name3 = "jinzhunew"

db.Raw("SELECT * FROM users WHERE (name1 = @name AND name3 = @name) AND name2 = @name2",
       map[string]interface{}{"name": "jinzhu", "name2": "jinzhu2"}).Find(&user)
// SELECT * FROM users WHERE (name1 = "jinzhu" AND name3 = "jinzhu") AND name2 = "jinzhu2"

type NamedArgument struct {
  Name  string
  Name2 string
}

db.Raw("SELECT * FROM users WHERE (name1 = @Name AND name3 = @Name) AND name2 = @Name2",
       NamedArgument{Name: "jinzhu", Name2: "jinzhu2"}).Find(&user)
// SELECT * FROM users WHERE (name1 = "jinzhu" AND name3 = "jinzhu") AND name2 = "jinzhu2"

8.3 Режим сухого прогона

Генерировать без выполнения SQL и其женьшеньчисло,Можетиспользуется для Подготовитьилитестгенерироватьиз SQL, подробности см. по ссылке. Session

Язык кода:javascript
копировать
var user User3
//session := db.Session(&gorm.Session{DryRun: true})
//session.First(&user, 1)
//fmt.Println(user)

stmt := db.Session(&gorm.Session{DryRun: true}).First(&user, 1).Statement
fmt.Println(stmt.SQL.String()) //=> SELECT * FROM `users` WHERE `id` = $1 ORDER BY `id`
fmt.Println(stmt.Vars)         //=> []interface{}{1}

8.4 ToSQL

Вернуть сгенерированный SQL Но не казнён.

GORMиспользовать database/sql заполнители параметров для создания SQL оператор, который автоматически экранирует аргументы, чтобы избежать SQL вводится, но мы не гарантируем создание SQL из Безопасность,Пожалуйста, используйте это только для отладки.

Язык кода:javascript
копировать
var users []User3
sql := db.ToSQL(func(tx *gorm.DB) *gorm.DB {
		return tx.Model(&User3{}).Where("id = ?", 100).Limit(10).Order("age desc").Find(&users)
	})
fmt.Println(sql)
//SELECT * FROM `user3` WHERE id = 100 ORDER BY age desc LIMIT 10

8.5 Row & Rows

получать *sql.Row результат

Язык кода:javascript
копировать
// использовать GORM API строить SQL
var name string
var age  int
row := db.Table("user3").Where("name = ?", "Одноклассник Сяосинь").Select("имя", "age").Row()
row.Scan(&name, &age)
fmt.Println(name)
fmt.Println(age)

// использовать Родной SQL
var name string
var age  int
row := db.Raw("select name, age from user3 where name = ?", «Одноклассник Сяосинь»).Row()
row.Scan(&name, &age)
fmt.Println(name)
fmt.Println(age)

получать *sql.Rows результат

Язык кода:javascript
копировать
// использовать GORM API строить SQL
var name string
var age int
rows, _ := db.Model(&User3{}).Where("name like ?", "%Xiaoxin%").Select("имя, age").Rows()
defer rows.Close()
for rows.Next() {
		rows.Scan(&name, &age)
		fmt.Printf("nameда:%s,ageда:%d\n",name,age)
}

// Родной SQL
var name string
var age int
rows, err := db.Raw("select name, age from user3 where name like ?", "%Xiaoxin%").Rows()
defer rows.Close()
for rows.Next() {
		rows.Scan(&name, &age)
		fmt.Printf("nameда:%s,ageда:%d\n",name,age)
}

Перейти к FindInBatches получатькаксуществоватьпартиясередина Запросииметь дело с Записыватьизинформация, Перейти к Group состояние получатькакстроитьсложный SQL Запросить информацию

8.6 Воля sql.Rows Сканировать в model

использовать ScanRows Воляодин ХОРОШОЗаписывать Сканировать в struct,Например:

Язык кода:javascript
копировать
rows, err := db.Model(&User3{}).Where("name like ?", "%Xiaoxin%").Select("имя,age").Rows()
defer rows.Close()
var user User3
for rows.Next() {
	// ScanRows Воляодин ХОРОШОСканировать в user
	db.ScanRows(rows, &user)
	fmt.Println(user)
}

8.7 Connection

Run mutliple SQL in same db tcp connection (not in a transaction)

Язык кода:javascript
копировать
db.Connection(func(tx *gorm.DB) error {
  tx.Exec("SET my.role = ?", "admin")

  tx.First(&User{})
})

8.8 Расширенный

Пункт

GORM uses SQL builder generates SQL internally, for each operation, GORM creates a *gorm.Statement object, all GORM APIs add/change Clause for the Statement, at last, GORM generated SQL based on those clauses

For example, when querying with First, it adds the following clauses to the Statement

Язык кода:javascript
копировать
clause.Select{Columns: "*"}
clause.From{Tables: clause.CurrentTable}
clause.Limit{Limit: 1}
clause.OrderByColumn{
  Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},
}

Then GORM build finally querying SQL in the Query callbacks like:

Язык кода:javascript
копировать
Statement.Build("SELECT", "FROM", "WHERE", "GROUP BY", "ORDER BY", "LIMIT", "FOR")

Which generate SQL:

Язык кода:javascript
копировать
SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1

You can define your own Clause and use it with GORM, it needs to implements Interface

Check out examples for reference

конструктор предложений

For different databases, Clauses may generate different SQL, for example:

Язык кода:javascript
копировать
db.Offset(10).Limit(5).Find(&users)
// Generated for SQL Server
// SELECT * FROM "users" OFFSET 10 ROW FETCH NEXT 5 ROWS ONLY
// Generated for MySQL
// SELECT * FROM `users` LIMIT 5 OFFSET 10

Which is supported because GORM allows database driver register Clause Builder to replace the default one, take the Limit as example

варианты пунктов

GORM defined Many Clauses, and some clauses provide advanced options can be used for your application

Although most of them are rarely used, if you find GORM public API can’t match your requirements, may be good to check them out, for example:

Язык кода:javascript
копировать
db.Clauses(clause.Insert{Modifier: "IGNORE"}).Create(&user)
// INSERT IGNORE INTO users (name,age...) VALUES ("jinzhu",18...);
StatementModifier

GORM provides interface StatementModifier allows you modify statement to match your requirements, take Hints as example

Язык кода:javascript
копировать
import "gorm.io/hints"

db.Clauses(hints.New("hint")).Find(&User{})
// SELECT * /*+ hint */ FROM `users`

10. Справочные документы

  • Документация официального сайта Gorm: [Интерфейс GORM CRUD](
boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose