PostgreSQL 匿名代码块(DO 语句)中的变量声明与使用

发布时间:2026/10/8 1:38:58
PostgreSQL 匿名代码块(DO 语句)中的变量声明与使用 文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载在 PL/pgSQL 中变量只能在函数Function的上下文里声明与使用而do匿名代码块正是无需创建持久化函数、即可临时体验这一机制的入口。本文基于 til 仓库的 use-variables-in-an-anonymous-function.md 文档结合仓库内其他 PostgreSQL 笔记完整讲解do语句的语法骨架、变量的声明与默认值、record类型在for循环中的迭代用法以及raise notice输出结果的方式读者学完后可以立刻在 psql 中复制运行并改造为自己的场景。为什么变量必须放进函数上下文PostgreSQL 的 SQL 语言本身并不提供类似脚本语言中的全局变量概念。一个变量必须有它的生命周期、类型和作用域而这些都只能在函数体的上下文中被定义。do语句允许我们写出一个匿名的 PL/pgSQL 代码块交给数据库临时编译并执行一次执行完毕后即被丢弃不会在数据库目录中留下任何对象。do $$ ... end $$;do块由三个固定组成declare段声明一个或多个变量并可选地给出默认值begin/end段实际要执行的 PL/pgSQL 语句体$$美元引号dollar quoting定界符用于包裹整个代码块避免与块内的单引号字符串冲突。关于美元引号仓库中的 escaping-string-literals-with-dollar-quoting.md 说明了它的价值当 SQL 由程序动态拼接、或字符串内部包含时传统写法需要连续写两个单引号转义见 two-ways-to-escape-a-quote-in-a-string.md容易出错。而 label-dollar-quoted-strings-with-a-tag.md 进一步指出定界符还可以带标签如$JSON$标签遵循非引号标识符的规则、区分大小写且不能包含$。给do块加上有意义的标签如$books$既能让代码块更可读也能规避块内出现$$序列的情况。声明变量类型 可选的默认值在declare段中每个变量声明都遵循同样的模式变量名、类型、可选的默认值。do $$ declare author_id varchar : e2b42ebf-7ea9-4d9e-8edf-310fc1894bcd; result record; begin ... end $$;这里出现了两种典型的声明写法author_id varchar : e2b42ebf-7ea9-4d9e-8edf-310fc1894bcd变量声明为varchar类型并用:赋予默认值一个 UUID 风格的作者标识符。:与在 PL/pgSQL 变量赋值中等价。result record;不指定默认值的变量。任何没有初始化的变量在进入begin段时都取该类型的零值——对record类型而言初始状态是未赋值unassigned只有在被select结果填充后才拥有字段结构。由于do块只是临时执行声明在其中的变量无法被块外引用这正好契合临时做实验、不想创建函数对象的场景。在 select 中直接使用变量变量声明后即可像普通值一样参与 SQL 表达式。下面的查询把author_id变量直接作为过滤条件select title from books where authorId author_id注意两点列名authorId使用了双引号包裹表明它是一个区分大小写的驼峰式列名。仓库笔记 table-names-are-treated-as-lower-case-by-default.md 指出未加引号的标识符会被 PostgreSQL 折叠为小写因此只有加双引号才能精确匹配建表时的驼峰命名。变量author_id与列authorId同名时不会冲突因为一个是 PL/pgSQL 变量、一个是列引用PostgreSQL 在语句内能正确区分但当变量名与列名完全一致时此处大小写不同所以无歧义推荐给变量加前缀避免可读性混乱。用 record 变量配合 FOR 循环迭代结果集record是 PL/pgSQL 中一种特殊的行变量它没有预定义结构而是在被赋值后动态继承来源查询的列结构。将它放进for ... loop中就可以逐行消费select的结果do $$ declare author_id varchar : e2b42ebf-7ea9-4d9e-8edf-310fc1894bcd; result record; begin for result in select title from books where authorId author_id loop raise notice | % |, result.title; end loop; end $$;执行流程是for result in query先执行查询得到结果集每轮循环把一行结果填入result此时result自动获得该查询的列结构这里只有title一列循环体内通过result.title访问该行的字段查询结束或没有匹配行时循环自然终止。这种写法的优势在于你不需要为每一行手工声明title的变量类型record会从查询结果中自动推断字段集合非常契合探索性实验和先跑通再说的场景。用 raise notice 输出结果do匿名代码块隐含的返回类型是void——它不向调用方返回任何值因此块内产生的数据必须在块内消费掉。raise notice正是为此服务它以NOTICE级别把消息写到服务器日志以及默认开启了client_min_messages的 psql 客户端。raise notice | % |, result.title;%是占位符后面的表达式result.title会按顺序替换进去| % |这种包裹写法只是演示效果方便在批量输出中肉眼区分每一行想要确认 psql 会话中能看到这些输出可以检查client_min_messages的设置默认包含notice级别。如果希望消费结果的同时把数据真正返回给调用方则应改为创建具名函数create function ... returns setof ...此时do块就不合适了。完整可运行的示例与输出效果把上述片段拼合即得到可在 psql 中直接执行的完整示例。假设books表结构与文档中一致含title列与authorId列且存在该作者的记录do $$ declare author_id varchar : e2b42ebf-7ea9-4d9e-8edf-310fc1894bcd; result record; begin for result in select title from books where authorId author_id loop raise notice | % |, result.title; end loop; end $$;运行后 psql 会打印类似下面的输出每本书一行NOTICE: | The Great Gatsby | NOTICE: | Tender Is the Night |若该author_id下没有书籍循环体不会执行代码块安静结束不报错、无输出——这正是空结果集的自然行为。与其他 PostgreSQL 笔记的关联关于美元引号定界符的转义细节与带标签写法见 escaping-string-literals-with-dollar-quoting.md 和 label-dollar-quoted-strings-with-a-tag.md文档示例中的books/authors表结构在仓库的 add-foreign-key-constraint-without-a-full-lock.md外键约束与 check-table-for-any-orphaned-records.md孤儿记录检查中也有出现可作为理解表关系的背景若你希望把匿名块中的逻辑固化为可复用对象edit-existing-functions.md 演示了如何用\ef直接打开并改写现有函数定义具名 PL/pgSQL 函数中使用变量的完整实践可参考 use-a-trigger-to-mirror-inserts-to-another-table.md触发器函数中的begin ... end与变量处理。小结do匿名代码块是探索 PostgreSQL 编程特性最轻量的入口它免去创建、维护、再删除函数的繁琐流程让变量声明declare 类型 :默认值、record行变量、for循环迭代和raise notice输出都能在一条语句内完成验证。当实验成熟、需要被反复调用时再把它升级为具名函数即可——这两者共享同一套 PL/pgSQL 的变量语义迁移成本极低。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐C Insights初始化if/switch条件语句中的变量声明C Insights初始化if/switch条件语句中的变量声明 还在为C17引入的if/switch初始化语句感到困惑吗想要真正理解编译器如何处理开发工具编译器PostgreSQL 命名语句实战使用 PREPARE、EXECUTE 与 DEALLOCATE 管理预编译语句PostgreSQL 命名语句实战使用 PREPARE、EXECUTE 与 DEALLOCATE 管理预编译语句 导读 在 PostgreSQL 中除了即时文档教程知识库Go 变量声明四问四答var 语法、先声明后使用、强类型与命名规则learngo 实战详解Go 变量声明四问四答var 语法、先声明后使用、强类型与命名规则learngo 实战详解 本文以 learngo 仓库中 06 variables/02示例工程教程上一篇Sharry完全指南自建文件分享平台的终极解决方案下一篇Samtools部署指南从源码编译到生产环境配置的完整流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考