事务语句
package main
/*
题目2:事务语句
假设有两个表: accounts 表(包含字段 id 主键, balance 账户余额)和 transactions 表
(包含字段 id 主键, from_account_id 转出账户ID, to_account_id 转入账户ID, amount 转账金额)。
要求 :
编写一个事务,实现从账户 A 向账户 B 转账 100 元的操作。在事务中,需要先检查账户 A 的余额是否足够,
如果足够则从账户 A 扣除 100 元,向账户 B 增加 100 元,并在 transactions 表中记录该笔转账信息。如果余额不足,则回滚事务。
*/
import (
"fmt"
"log"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Account struct {
ID uint `gorm:"primaryKey"`
Balance int
}
type Transaction struct {
ID uint `gorm:"primaryKey"`
FromAccountID uint
ToAccountID uint
Amount int
}
func main() {
//配置MySQL连接参数
username := "root" //账号
password := "gjs199074" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "web3_test" //数据库名
timeout := "10s" //连接超时,10秒
//拼接dsn参数,这里使用Sprintf动态拼接
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("连接数据库失败, error=" + err.Error())
}
fmt.Println(db)
fmt.Println("连接成功")
// 自动迁移表结构
db.AutoMigrate(&Account{}, &Transaction{})
// 初始化账户A余额为500
db.FirstOrCreate(&Account{ID: 1, Balance: 500})
db.FirstOrCreate(&Account{ID: 2, Balance: 0})
// 示例转账
fromAccountID := uint(1)
toAccountID := uint(2)
amount := 100
if err := TransferMoney(db, fromAccountID, toAccountID, amount); err != nil {
log.Printf("转账失败: %v", err)
} else {
log.Println("转账成功")
}
}
func TransferMoney(db *gorm.DB, fromID, toID uint, amount int) error {
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err := tx.Error; err != nil {
return err
}
// 检查转出账户余额
var fromAccount Account
if err := tx.First(&fromAccount, fromID).Error; err != nil {
tx.Rollback()
return fmt.Errorf("查询转出账户失败: %w", err)
}
if fromAccount.Balance < amount {
tx.Rollback()
return fmt.Errorf("账户余额不足")
}
// 更新账户余额
if err := tx.Model(&Account{}).Where("id = ?", fromID).
Update("balance", gorm.Expr("balance - ?", amount)).Error; err != nil {
tx.Rollback()
return fmt.Errorf("扣除转出账户失败: %w", err)
}
if err := tx.Model(&Account{}).Where("id = ?", toID).
Update("balance", gorm.Expr("balance + ?", amount)).Error; err != nil {
tx.Rollback()
return fmt.Errorf("增加转入账户失败: %w", err)
}
// 记录交易
transaction := Transaction{
FromAccountID: fromID,
ToAccountID: toID,
Amount: amount,
}
if err := tx.Create(&transaction).Error; err != nil {
tx.Rollback()
return fmt.Errorf("记录交易失败: %w", err)
}
return tx.Commit().Error
}
查询语句
package main
/*
题目1:使用SQL扩展库进行查询
假设你已经使用Sqlx连接到一个数据库,并且有一个 employees 表,包含字段 id 、 name 、 department 、 salary 。
要求 :
编写Go代码,使用Sqlx查询 employees 表中所有部门为 "技术部" 的员工信息,并将结果映射到一个自定义的 Employee 结构体切片中。
编写Go代码,使用Sqlx查询 employees 表中工资最高的员工信息,并将结果映射到一个 Employee 结构体中。
*/
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Employee struct {
ID int
Name string
Department string
Salary int
}
func main() {
//配置MySQL连接参数
username := "root" //账号
password := "gjs199074" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "web3_test" //数据库名
timeout := "10s" //连接超时,10秒
//拼接dsn参数,这里使用Sprintf动态拼接
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("连接数据库失败, error=" + err.Error())
}
fmt.Println(db)
fmt.Println("连接成功")
db.AutoMigrate(&Employee{})
Employees := []*Employee{
{ID: 1, Name: "小张", Department: "技术部", Salary: 7000},
{ID: 2, Name: "小王", Department: "市场部", Salary: 6000},
{ID: 3, Name: "小李", Department: "技术部", Salary: 8000},
{ID: 4, Name: "小可", Department: "技术部", Salary: 9000},
}
result1 := db.Create(&Employees) //通过数据指针来创建
println(result1.RowsAffected)
// 查询技术部员工
// 查询技术部员工
var techEmployees []Employee
result := db.Where("Department = ?", "技术部").Find(&techEmployees)
if result.Error != nil {
fmt.Println("查询失败:", result.Error)
return
}
// 打印技术部员工信息
fmt.Println("技术部员工信息:")
for _, emp := range techEmployees {
fmt.Printf("ID: %d, Name: %s, Department: %s, Salary: %d\n", emp.ID, emp.Name, emp.Department, emp.Salary)
}
// 并将结果映射到一个自定义的 Employee 结构体切片中
// 查询工资最高的员工
var highestPaidEmployee Employee
result2 := db.Order("Salary DESC").First(&highestPaidEmployee)
if result2.Error != nil {
fmt.Println("查询失败:", result2.Error)
return
}
// 打印工资最高的员工信息
fmt.Println("工资最高的员工信息:")
fmt.Printf("ID: %d, Name: %s, Department: %s, Salary: %d\n", highestPaidEmployee.ID, highestPaidEmployee.Name, highestPaidEmployee.Department, highestPaidEmployee.Salary)
}
基本CRUD
/*
目1:基本CRUD操作
假设有一个名为 students 的表,包含字段 id (主键,自增)、 name (学生姓名,字符串类型)、 age (学生年龄,整数类型)、 grade (学生年级,字符串类型)。
要求 :
编写SQL语句向 students 表中插入一条新记录,学生姓名为 "张三",年龄为 20,年级为 "三年级"。
编写SQL语句查询 students 表中所有年龄大于 18 岁的学生信息。
编写SQL语句将 students 表中姓名为 "张三" 的学生年级更新为 "四年级"。
编写SQL语句删除 students 表中年龄小于 15 岁的学生记录。
*/
// -- 插入新记录
// INSERT INTO students (name, age, grade) VALUES ('张三', 20, '三年级');
// -- 查询年龄大于18岁的学生
// SELECT * FROM students WHERE age > 18;
// -- 更新张三的年级
// UPDATE students SET grade = '四年级' WHERE name = '张三';
// -- 删除年龄小于15岁的学生
// DELETE FROM students WHERE age < 15;
// 使用golang去执行上述SQL语句
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Student struct {
gorm.Model
ID int
Name string
Age int
Grade string
}
func main() {
//配置MySQL连接参数
username := "root" //账号
password := "gjs199074" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "web3_test" //数据库名
timeout := "10s" //连接超时,10秒
//拼接dsn参数,这里使用Sprintf动态拼接
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("连接数据库失败, error=" + err.Error())
fmt.Println(db)
fmt.Println("连接成功")
}
db.AutoMigrate(&Student{})
students := []*Student{
{ID: 1, Name: "张三", Age: 20, Grade: "三年级"},
{ID: 2, Name: "小王", Age: 34, Grade: "八年级"},
{ID: 3, Name: "小李", Age: 12, Grade: "九年级"},
{ID: 4, Name: "小可", Age: 21, Grade: "六年级"},
}
result1 := db.Debug().Create(&students) //通过数据指针来创建
println(result1.RowsAffected)
//查询数据
result2 := db.Debug().Where("age > ?", 18).Find(&students)
println(result2.RowsAffected)
//更新数据
result3 := db.Debug().Model(&Student{}).Where("name = ?", "张三").Update("grade", "四年级")
println(result3.RowsAffected)
//删除数据
result4 := db.Debug().Where("age < ?", 15).Delete(&Student{})
println(result4.RowsAffected)
}
GORM 模型定义
package main
/*
题目1:模型定义
假设你要开发一个博客系统,有以下几个实体: User (用户)、 Article (文章)、 Comment (评论)。
要求 :
使用Gorm定义 User 、 Article 和 Comment 模型,其中 User 与 Article 是一对多关系(一个用户可以发布多篇文章),
Article 与 Comment 也是一对多关系(一篇文章可以有多个评论)。
编写Go代码,使用Gorm创建这些模型对应的数据库表。
*/
import (
"fmt"
"log"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Username string `gorm:"unique;not null"`
Email string `gorm:"type:varchar(255);not null"`
Password string `gorm:"not null"`
Articles []Article `gorm:"foreignKey:UserID"`
}
type Article struct {
gorm.Model
Title string `gorm:"not null"`
Content string `gorm:"type:text"`
UserID uint `gorm:"not null"`
Comments []Comment `gorm:"foreignKey:ArticleID"`
}
type Comment struct {
gorm.Model
Content string `gorm:"type:text"`
ArticleID uint `gorm:"not null"`
UserID uint `gorm:"not null"`
}
func main() {
//配置MySQL连接参数
username := "root" //账号
password := "gjs199074" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "web3_test" //数据库名
timeout := "10s" //连接超时,10秒
//拼接dsn参数,这里使用Sprintf动态拼接
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("连接数据库失败, error=" + err.Error())
}
fmt.Println(db)
fmt.Println("连接成功")
// 自动迁移模型
err = db.AutoMigrate(&User{}, &Article{}, &Comment{})
if err != nil {
log.Fatal("Failed to migrate tables:", err)
}
fmt.Println("Database tables created successfully!")
//创建用户、文章、评论
var users = []User{
{Username: "科比", Email: "112345678@QQ.COM", Password: "123456", Articles: []Article{
{Title: "GORM教程", Content: "这是关于GORM的教程文章", UserID: 1, Comments: []Comment{
{Content: "很有帮助的文章!", UserID: 1, ArticleID: 1}}}}},
{Username: "乔丹", Email: "112345678@QQ.COM", Password: "123456", Articles: []Article{
{Title: "GORM高级用法", Content: "这是关于GORM的高级用法文章", UserID: 2, Comments: []Comment{
{Content: "学到了很多新知识!", UserID: 2, ArticleID: 2}, {Content: "太强了学到好多知识,给你点赞!", UserID: 2, ArticleID: 2}}}}}}
result1 := db.Create(users) //通过数据切片来创建
println(result1.RowsAffected)
// 查询某个用户发布的所有文章及其对应的评论信息
var user User
userID := 1 // 假设要查询的用户 ID 为 1
err = db.Preload("Articles.Comments").First(&user, userID).Error
if err != nil {
fmt.Println("查询失败:", err)
return
}
// 打印结果
fmt.Printf("用户: %s\n", user.Username)
for _, article := range user.Articles {
fmt.Printf("文章: %s\n", article.Title)
for _, comment := range article.Comments {
fmt.Printf("评论: %s\n", comment.Content)
}
}
// 查询评论数量最多的文章信息
var article Article
err = db.Model(&Article{}).
Select("articles.*, COUNT(comments.id) as comment_count ").
Joins("left join comments on comments.article_id = articles.id").
Group("articles.id").
Order("comment_count DESC").
Limit(1).
Find(&article).Error
if err != nil {
fmt.Println("查询失败:", err)
return
}
// 打印结果
fmt.Printf("评论数量最多的文章: %s\n", article.Title)
}
评论区