当前位置:首页 > 文章列表 > 文章 > 软件教程 > sqlc 可空查询参数怎么生成指针或 Null 类型

sqlc 可空查询参数怎么生成指针或 Null 类型

来源:17golang原创 2026-11-05 12:56:17 0浏览 收藏

sqlc 生成可空查询参数时,关键不是把整个参数结构体改成指针,而是先在 SQL 中使用 sqlc.narg() 明确参数可为空。默认配置通常会得到 sql.NullString、sql.NullInt64 这类 Null 类型;在支持的 PostgreSQL pgx/v4、pgx/v5 或 SQLite 场景中,再打开 emit_pointers_for_null_types: true,才可以让可空类型表现为 *string、*int64。

官方地址:https://docs.sqlc.dev/en/stable/

下面用一个“只更新传入字段”的查询做对照,重点看 SQL 标记、生成配置、Params 字段和调用方式四个位置。

先把可空参数写在 SQL 里

sqlc 会根据 SQL 上下文推断参数是否可空。如果希望一个参数无论上下文如何都按可空参数生成,就使用 sqlc.narg。它和 sqlc.arg 一样可以给参数命名,但额外覆盖了可空性推断。

-- name: UpdateAuthor :one
UPDATE authors
SET
    name = COALESCE(sqlc.narg('name'), name),
    bio = COALESCE(sqlc.narg('bio'), bio)
WHERE id = sqlc.arg('id')
RETURNING *;

这里的 name 和 bio 是可空参数,id 仍然是普通的非空参数。COALESCE 只是这个更新场景的示例,文章关注的是生成出来的参数类型,不讨论数据库字段本身的 NULL 设计。

先分清三个容易混淆的设置

生成类型之前,先把三个配置分开。它们作用在不同层级:

配置或写法改变什么不会改变什么
sqlc.narg()把 SQL 参数标为 nullable不会直接决定使用指针还是 Null 包装
emit_pointers_for_null_types让支持的可空类型生成 *T不会把普通非空字段改成指针
emit_params_struct_pointers让调用方法接收 *UpdateAuthorParams不会把其中的字段改成 *string

因此,看到 *UpdateAuthorParams 时不要误以为 Name 一定是 *string。参数结构体的指针和结构体字段的可空类型是两条独立配置链。

原创 sqlc 配置界面说明图,展示 sqlc.narg、pgx/v5 和可空指针设置的关系
图1:可空参数配置的界面说明图,展示 SQL 标记、驱动选择和指针设置的对应关系;这是原创操作示意图,不是实际软件截图。

默认 Null 类型:调用时看 Valid

不打开指针选项时,常见生成结果如下。以 database/sql 的字符串为例,字段通过 Valid 区分“有值”和“应传 NULL”。

type UpdateAuthorParams struct {
    // Valid=false 时由驱动传递 NULL,避免把空字符串误当成缺省值。
    Name sql.NullString
    // 同一个规则适用于第二个可选字段。
    Bio  sql.NullString
    // id 由 sqlc.arg 生成普通的非空参数。
    ID   int64
}

params := UpdateAuthorParams{
    // Valid=true 才会把 String 作为参数值传入。
    Name: sql.NullString{String: "Ada", Valid: true},
    // Valid=false 表示本次不更新 bio。
    Bio:  sql.NullString{Valid: false},
    ID:   7,
}
author, err := queries.UpdateAuthor(ctx, params)
if err != nil {
    // 保留生成方法返回的数据库错误,交给上层处理。
    return err
}
_ = author

默认 Null 类型的优点是语义明确:值和有效性放在同一个字段里。代价是调用方需要构造包装类型,不能直接把普通字符串赋给 Name。

支持的场景下改成指针类型

如果项目使用 PostgreSQL 的 pgx/v4、pgx/v5,或使用 SQLite,可以在 Go 生成配置中打开指针选项。配置重点如下:

version: "2"
sql:
  - engine: postgresql
    schema: db/schema.sql
    queries: db/query.sql
    gen:
      go:
        package: db
        out: internal/db
        sql_package: pgx/v5
        # 让可空字符串等类型生成 *string,而不是 Null 包装类型。
        emit_pointers_for_null_types: true

在这个支持范围内,前面的可空参数可以表现为类似下面的结构:

type UpdateAuthorParams struct {
    // nil 表示本次参数为 NULL;非 nil 指向要传入的字符串。
    Name *string
    // nil 让调用方不必额外构造 NullString。
    Bio  *string
    // 非空参数仍然是普通值类型。
    ID   int64
}

name := "Ada"
params := UpdateAuthorParams{
    // 传地址表示有值,传 nil 表示 NULL。
    Name: &name,
    Bio:  nil,
    ID:   7,
}
_, err := queries.UpdateAuthor(ctx, params)
if err != nil {
    // 生成方法的错误仍按普通 Go 错误处理。
    return err
}

不要把这个选项当成所有数据库和驱动的通用开关。sqlc 当前文档对支持范围有明确限制;如果驱动不在支持范围内,优先接受默认 Null 类型,或改用明确的类型覆盖。

需要业务类型时用 nullable override

如果你想用自己的类型表达可空值,配置 overrides 时要明确写 nullable: true。如果目标类型需要指针,再在 go_type 中写 pointer: true。只写非空覆盖不会自动覆盖可空参数。

version: "2"
sql:
  - engine: postgresql
    schema: db/schema.sql
    queries: db/query.sql
    gen:
      go:
        package: db
        out: internal/db
        sql_package: pgx/v5
        overrides:
          # 非空 uuid 和可空 uuid 要分别声明覆盖规则。
          - db_type: uuid
            nullable: true
            go_type:
              import: github.com/google/uuid
              type: UUID
              pointer: true

这个方案适合团队已经统一使用某个值对象的项目。它的注意点是:db_type 覆盖默认只匹配一种可空性;同一数据库类型如果既有非空字段又有可空字段,通常需要分别写两条覆盖规则。

调用前按生成结果做一次核对

配置保存后,重点不是盯着配置面板,而是打开生成文件确认 Params 结构体。可以按下面顺序核对:

  1. SQL 中可选参数是否确实使用了 sqlc.narg。
  2. 指针模式下字段是否为 *T,默认模式下是否为对应的 sql.NullT。
  3. 只有 emit_params_struct_pointers 时,方法参数是否是 *UpdateAuthorParams,字段类型是否保持原配置。
  4. 调用代码是否把 nil 或 Valid=false 当成同一个“传 NULL”语义,而不是把空字符串当成缺省值。
原创 sqlc 生成代码核对界面说明图,展示 UpdateAuthorParams 的指针字段与 Null 类型对照
图2:生成结果核对的界面说明图,重点看 Params 字段类型和调用语义;这是原创结果示意图,不是实际软件截图。

几个常见误区

把 emit_params_struct_pointers 当成字段指针开关。它只影响参数结构体的传递方式,不能替代 emit_pointers_for_null_types 或 nullable override。

只写 sqlc.arg 期待得到可空参数。sqlc.arg 主要负责命名和参数标记;需要强制 nullable 时用 sqlc.narg。

在不支持的驱动上强行期待 *T。先看 sqlc 配置文档对引擎和 sql_package 的限制;不满足时,sql.NullString 等默认类型往往是更可靠的生成结果。

override 漏写 nullable。同一个数据库类型的非空和可空映射不是一条规则自动覆盖,必须按可空性分别配置。

结论

想让 sqlc 生成可空查询参数,先用 sqlc.narg 表达参数语义,再根据驱动选择类型表达:默认使用 sql.NullT,支持的 PostgreSQL pgx 或 SQLite 可用 emit_pointers_for_null_types 生成 *T,特殊业务类型则用带 nullable: true 的 override。最后只检查生成的 Params 字段和调用代码,就能避免把结构体指针、字段指针和 Null 包装混为一谈。

相关问题

sqlc.narg 和 sqlc.arg 有什么区别?前者会强制把参数标记为 nullable,后者主要用于命名和普通参数标记。

为什么打开 emit_params_struct_pointers 后仍然是 sql.NullString?因为它只改变 Params 结构体本身的传参形式,不改变字段的可空类型。

指针模式下如何表达“不更新这个字段”?对支持的生成类型传入 nil;默认 Null 模式则让对应字段的 Valid 为 false。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
grpcui 调试 gRPC 时怎么为请求添加 metadata 头grpcui 调试 gRPC 时怎么为请求添加 metadata 头
上一篇
grpcui 调试 gRPC 时怎么为请求添加 metadata 头
Atlas migrate lint 怎么在部署前检查迁移是否可重放
下一篇
Atlas migrate lint 怎么在部署前检查迁移是否可重放
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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模型性能。
    893次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    894次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    978次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    967次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    793次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码