当前位置:首页 > 文章列表 > Golang > Go教程 > Go Squirrel 怎样用 PlaceholderFormat 转换数据库占位符

Go Squirrel 怎样用 PlaceholderFormat 转换数据库占位符

来源:17golang原创 2026-10-29 12:24:53 0浏览 收藏

Go Squirrel 的占位符转换,核心就是在构造器上设置 PlaceholderFormat:默认的 Question 保留 ?,PostgreSQL 常用 Dollar 生成 $1、$2,还可以选择 Colon 或 AtP。转换只改 SQL 文本,不会把参数值拼进 SQL;args 仍按出现顺序传给 database/sql。

官方资料:https://github.com/Masterminds/squirrel

要点速览
  • 统一配置优先放在 StatementBuilder,单个查询也可单独覆盖。
  • ToSql() 同时返回 SQL、args 和 error,先看三者是否匹配。
  • 子查询最终由父查询统一转换;PostgreSQL 字面问号写成 ??。

先选对 PlaceholderFormat,再生成 SQL

Squirrel 的默认格式是 Question,适合继续使用问号占位符的驱动。若目标驱动使用 PostgreSQL 风格的位置参数,可把构造器改成 sq.Dollar。四种内置格式可以这样理解:

格式SQL 中的结果常见场景
Question?问号占位符驱动
Dollar$1、$2PostgreSQL
Colon:1、:2冒号位置参数
AtP@p1、@p2SQL Server 风格
Go Squirrel PlaceholderFormat 将问号占位符映射到 Dollar、Colon 和 AtP 的说明图
图1:PlaceholderFormat 的占位符映射说明图,不是运行截图。

最小用法是先用问号写条件,再在构造器上选择格式:

package main

import (
    "fmt"

    sq "github.com/Masterminds/squirrel"
)

func main() {
    // 先用通用的 ? 表达条件,最终由 PlaceholderFormat 负责转换。
    builder := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
    query := builder.Select("id", "name").
        From("users").
        Where("status = ? AND age > ?", "active", 18)

    // ToSql 同时返回 SQL 文本、参数顺序和构造错误。
    sqlText, args, err := query.ToSql()
    if err != nil {
        panic(err) // 示例中直接终止;生产代码应向上返回错误。
    }
    fmt.Println(sqlText) // SELECT id, name FROM users WHERE status = $1 AND age > $2
    fmt.Printf("%v\n", args) // [active 18]
}

实际字段条件的排序由构造器处理,但使用时不要把 $1、$2 手工写入普通条件。让 Squirrel 统一编号,args 才不容易错位。

全局配置和单个查询覆盖怎么选

同一个数据库连接池通常只对应一种占位符风格,可以从 StatementBuilder 统一设置;如果一个服务同时连接不同数据库,则让每个查询或每组 builder 明确声明格式。

// PostgreSQL 查询统一生成 $1、$2;args 仍然单独传递。
postgres := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
sqlText, args, err := postgres.
    Select("id").
    From("orders").
    Where("user_id = ? AND state = ?", 42, "paid").
    ToSql()
if err != nil {
    return err // 生产代码把构造失败交给调用方处理。
}
// sqlText: ... user_id = $1 AND state = $2
// args: [42 paid]
_ = sqlText
_ = args

也可以只在一个 builder 上调用 .PlaceholderFormat(sq.Question) 或其他格式。这个覆盖只影响当前 builder,不会把同一组 args 复制或重排。执行时仍应把返回值整体交给驱动:

// SQL 和 args 必须成对传入,不能把参数拼接进字符串。
rows, err := db.QueryContext(ctx, sqlText, args...)
if err != nil {
    return err // 查询失败时立即返回,避免继续读取无效 rows。
}
defer rows.Close() // 释放数据库结果集资源。

嵌套查询和字面问号怎么处理

嵌套查询最容易出现“子查询已经编号,父查询又从 1 开始编号”的问题。稳妥做法是:子查询和拼接片段先保持 ?,父查询完成组合后,再在最终 builder 上设置 Dollar 并调用 ToSql()。这样转换器只处理最终 SQL 文本,参数顺序由组合过程保持。

// 子查询先保留 ?,父查询完成组合后统一转换为 $1、$2。
sub := sq.Select("id").
    From("users").
    Where("tenant_id = ?", tenantID)

root := sq.Select("id", "name").
    FromSelect(sub, "u").
    Where("state = ?", "active").
    PlaceholderFormat(sq.Dollar)

sqlText, args, err := root.ToSql()
if err != nil {
    return err // 先处理构造错误,再交给数据库执行。
}
// 最终占位符应按 args 的顺序编号。
_, _ = sqlText, args

如果 SQL 本身需要 PostgreSQL 的 JSON 运算符 ?,Squirrel 会把问号当作占位符入口。用两个问号 ?? 表示字面问号,后面的真正参数占位符再继续编号,例如 meta->'format' ??| array[?,?] 会保留运算符问号,并把数组参数转换成连续的位置参数。

Go Squirrel 子查询统一转换占位符并处理 PostgreSQL 字面问号的结构图
图2:嵌套查询与字面问号的边界结构图,不是运行截图。

生成后用这张清单排查错位

  • 驱动需要什么格式:确认使用的是 Question、Dollar、Colon 还是 AtP。
  • SQL 里有几个真实参数:逐个对照 args 的长度和顺序。
  • 是否混用了已编号参数:普通片段不要手写 $1,交给最终 builder 转换。
  • 是否存在字面问号:PostgreSQL 运算符中的问号写成 ??。

相关问题

PlaceholderFormat 会修改 args 吗?

不会。它主要替换 SQL 中的占位符文本,参数仍以 Squirrel 组合时的顺序返回。

单个查询可以覆盖全局格式吗?

可以,在具体的 Select、Insert、Update 或 Delete builder 上再次调用 PlaceholderFormat 即可。

为什么不直接把值拼进 SQL?

拼接会破坏参数化查询和转义边界。保留占位符并传入 args,才能让驱动负责参数绑定。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go Squirrel 怎样用 Expr 把表达式与绑定参数组合起来Go Squirrel 怎样用 Expr 把表达式与绑定参数组合起来
上一篇
Go Squirrel 怎样用 Expr 把表达式与绑定参数组合起来
Go Validator 怎样为切片元素配置 dive 规则
下一篇
Go Validator 怎样为切片元素配置 dive 规则
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    774次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    770次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    856次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    821次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    651次使用