当前位置:首页 > 技术 > 正文内容

GORM中执行原始SQL语句的方法与技巧

访客 技术 2026年8月11日 1

GORM中执行原始SQL语句的方法与技巧

  1. GORM更新单一字段
func (repo *repository) ModifySingleField(entity *Entity) bool {
    updateErr := repo.Database.Model(Entity{}).Where("entity_id = ?", entity.EntityID).Updates(map[string]interface{}{
        "status": entity.Status,
    }).Error
    if updateErr != nil {
        repo.Logger.Error(updateErr)
        return false
    }
    return true
}
  1. GORM基本数据查询
func (repo *repository) FetchUserByUserID(userID int) (result User) {
    if userID <= 0 {
        repo.Logger.Error("Invalid parameter")
        return
    }
    
    queryErr := repo.Database.Model(User{}).Where("user_id = ?", userID).First(&result).Error
    if queryErr != nil {
        repo.Logger.Error(queryErr)
    }
    return
}

type User struct {
    UserID   int    `json:"user_id"`
    UserName string `json:"user_name"`
}

func (User) TableName() string {
    return "user_info"
}
  1. GORM多表关联与条件筛选
import (
    "database/sql"
    "github.com/jinzhu/gorm"
)

type dataHandler struct {
    database *sql.DB
}

var handler *dataHandler
var Database *gorm.DB

func (*dataHandler) RetrieveComplexData(currentPage, limit int, searchName, searchAge, category string, statusType int) (results []UserData, totalCount int) {
    if limit > 20 {
        limit = 20
    }
    if currentPage <= 0 {
        currentPage = 1
    }
    
    query := Database.Table("main_table as mt").Select(
        "mt.user_name as user_name," +
        "ma.age as age," +
        "mc.created_time as created_time," +
        "mc.state as state")
    
    if searchName != "" {
        query = query.Where("mt.identifier = ?", searchName)
    }

    if searchAge != "" {
        query = query.Where("mt.shipment_ref = ?", searchAge)
    }

    if category != "" {
        query = query.Where("mt.tracking_num = ?", category)
    }
    
    query = query.Where("mt.transport_type = ?", statusType)
    query = query.Joins("left join secondary_table on secondary_table.ref_id = mt.main_id")
    query = query.Joins("right join user_details on mc.tracking_num = mt.tracking_num")
    query = query.Order("transport_time").Limit(limit).Offset((currentPage - 1) * limit)
    
    scanErr := query.Count(&totalCount).Scan(&results).Error
    if scanErr != nil {
        app.Logger.Errorf("Query failed: %s", scanErr)
        return
    }

    return
}
  1. GORM执行原始SQL语句

方法一:使用Database.Raw

type DeviceAlert struct {
    DeviceID string `json:"device_id"`
    AlertType int   `json:"alert_type"`
}

func (repo *repository) FetchAlertsByDeviceIDs(companyID string, deviceList []string) (alerts []DeviceAlert) {
    if len(deviceList) == 0 {
        repo.Logger.Error("Empty device list")
        return
    }
    
    deviceClause := "('" + strings.Join(deviceList, "','") + "')"
    queryString := fmt.Sprintf(`
    SELECT 
    payload::json->>'device_id' as device_id,
    alert_category as alert_type
    FROM notification_table where record_id in  (
    SELECT max(record_id) as record_id FROM notification_table WHERE company_id = '%s' and payload::json->>'device_id' in %s  GROUP BY payload::json->>'device_id'
    )
    `, companyID, deviceClause)
    
    executionResult := repo.Database.Raw(queryString).Scan(&alerts)
    if executionResult.Error != nil {
        repo.Logger.Error(executionResult.Error)
        return
    }
    return
}

方法二:使用Database.QueryRow

func (repo repository) GetDataByRef(refCode string) *ReferenceData {
    record := new(ReferenceData)
    var queryBuilder string
    
    switch {
    case len(refCode) > 0:
        queryBuilder += fmt.Sprintf(" and \"reference_code\" = '%s'", refCode)
    default:
        repo.Logger.Error("Parameter validation failed")
        return nil
    }
    
    baseSQL := `
    select
    coalesce("reference_code",'') as ReferenceCode,
    coalesce(description,'') as Description,
    coalesce(title,'') as Title,
    coalesce(model,'') as Model,
    coalesce(color,'') as Color
    from reference_table
    where 1=1
    `
    baseSQL += queryBuilder
    
    scanErr := repo.DatabaseReadOnly.QueryRow(baseSQL).Scan(&record.ReferenceCode, &record.Description, &record.Title, &record.Model, &record.Color)
    if scanErr != nil {
        repo.Logger.Errorf("Parameters=%s, SQL=%s, Error=%v", refCode, baseSQL, scanErr)
        return nil
    }
    return record
}

方法三:使用Database.Raw配合rows.next

// 执行原始SQL查询
resultSet, queryErr := database.Raw("select username, user_age, contact_email from user_profiles where username = ?", "john_doe").Rows()
defer resultSet.Close()

for resultSet.Next() {
    var userName string
    var userAge int
    var email string
    
    resultSet.Scan(&userName, &userAge, &email)
    // 处理每行数据
}
  1. SQL分组后获取首条记录
SELECT
    *
FROM
    ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY customer_id ORDER BY last_updated DESC ) AS row_num FROM customer_data WHERE customer_id IN ( 2,3,4 ) and active_status = 1 ) subquery 
WHERE
    subquery.row_num = 1
  1. GORM执行原始UPDATE语句
rawSQL := `UPDATE target_table SET column_name = 'new_value' WHERE condition_column = 'condition_value'`
executionErr := dbContext.Exec(rawSQL).Error
if executionErr != nil {
    logger.WithContext(contextInstance).Error(executionErr)
    return executionErr
}
标签: GORMSQL

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。