ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

TIL 技术笔记:PostgreSQL 美元引用(Dollar Quoting)——用 $$ 优雅转义字符串字面量

TIL 技术笔记:PostgreSQL 美元引用(Dollar Quoting)——用 $$ 优雅转义字符串字面量 文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载本篇笔记来自 TILToday I Learned仓库的 PostgreSQL 分类系统讲解 PostgreSQL 的美元引用Dollar Quoting语法。它以字符串转义为切入点先回顾单引号定界字符串的转义痛点再演示如何用$$或$tag$...$tag$包裹字符串字面量从而彻底避开转义陷阱并延伸到DO匿名块、函数体定义与程序化生成 SQL 等实战场景。读完本文你将掌握在 psql 与 SQL 脚本中安全书写含引号字符串的完整方法。字符串字面量单引号定界与转义痛点PostgreSQL 中字符串字面量包括varchar、text等类型的常规定义方式是用单引号包裹内容。问题随之而来当字符串内容本身包含单引号时必须对引号进行转义否则解析器会把内容中间的误认为是字面量的结束符。最常见的转义手法是将单引号写成两个连续的单引号第一个单引号让第二个单引号被转义最终内容中保留一个单引号 select Isnt this nice?; ?column? ------------------ Isnt this nice?仓库中另有一篇姊妹笔记 postgres/escaping-a-quote-in-a-string.md 对此做了同样验证whats up!会得到whats up!。而 postgres/two-ways-to-escape-a-quote-in-a-string.md 则补充了第二种转义手段——在字符串前加E前缀启用转义序列语法用反斜杠转义引号 select Ewho\s on first?; ?column? ----------------- whos on first? (1 row)如果不做任何转义直接书写whos on first?查询将永远无法执行——psql 会认为还有一组引号没有闭合一直在等待输入。这两种转义手段虽然可行但在实际使用中都有明显短板容易出错字符串中引号越多需要书写的或\就越多肉眼核对成本很高不利于程序化生成 SQL当 SQL 由代码动态拼接例如遍历一批含撇号的用户输入去构造查询时逐字符判断要不要转义非常繁琐极易漏转义或错转义。这正是美元引用Dollar Quoting要解决的问题。美元引用用$$包裹字符串免去转义美元引用的思路非常简单用一对$$替代首尾的单引号来包裹字符串。只要字符串内容中不出现连续的$$序列内部的单引号、反斜杠等内容都会被当作普通字符按字面处理完全不需要转义 select $$Isnt this even nicer?$$; ?column? ------------------------ Isnt this even nicer?对比前文Isnt中的单引号在$$包裹下原样保留无需写成。书写规则只有一个核心点把字符串两端的定界符从换成$$即可。从词法层面看美元引用是 PostgreSQL 定义的一类独立字符串常量形式官方词法文档中称之为 Dollar-Quoted String Constants其定界符与普通单引号字符串互不干扰因此两类字符串可以自由混合使用。这意味着在处理大量含引号的文本HTML、Shell 命令、带有撇号的用户内容等时美元引用是更省心的选择。带标签的美元引用$tag$ ... $tag$基础版$$...$$有一个局限如果字符串内容里恰好出现了连续的$$序列定界符就会被提前截断。另外$$本身不带任何语义信息。针对这两个问题PostgreSQL 提供了带标签的美元引用语法为$tag$...$tag$首尾标签必须完全一致。仓库姊妹笔记 postgres/label-dollar-quoted-strings-with-a-tag.md 给出了一个极具代表性的场景——直接书写一段可转换为jsonb的 JSON 文本。JSON 中既有撇号Sallys又有连续的$$$序列用普通单引号几乎无法优雅书写而带标签的美元引用可以原样搞定 select $JSON${name: Sallys Bistro, price: $$$}$JSON$::jsonb; jsonb -------------------------------------------- {name: Sallys Bistro, price: $$$} (1 row) select $JSON${name: Sallys Bistro, price: $$$}$JSON$::jsonb-name as name; name ------------------ Sallys Bistro (1 row)这里的标签是JSON它传递了这个字符串字面量代表一段 JSON的语义信息。第二个示例还展示了转换后的值可以像普通jsonb一样参与查询操作通过-提取name字段说明美元引用产出的就是普通字符串常量转换与运算完全不受影响。标签本身遵循明确的命名约束标签遵循与未加引号标识符相同的规则唯一例外是不能包含美元符号$且标签区分大小写。因此在自定义标签时应使用字母、数字和下划线等常规字符。美元引用的典型实战场景1.DO匿名块声明变量与流程控制DO语句可以声明并执行一段匿名 PL/pgSQL 代码块。代码块本身往往含有多条语句、变量声明甚至嵌套的 SQL这些内容里极易出现单引号因此用美元引用包裹块体是标准做法。仓库笔记 postgres/use-variables-in-an-anonymous-function.md 演示了完整的do $$ ... $$写法在块内声明带默认值的变量、用for循环遍历查询结果、并用raise notice输出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 $$;注意两个细节一是变量声明里就含有字符串默认值单引号二是raise notice的格式化字符串里也有单引号外层一旦用$$包裹内部所有单引号都不必再转义。由于匿名do块隐式返回void需要在块内消费查询结果——本例用raise notice打印每条书名。2. 函数与过程体定义美元引用在定义CREATE FUNCTION、CREATE PROCEDURE的函数体时同样实用函数体内往往嵌着大量 SQL 语句而 SQL 语句中又可能出现单引号字面量。若用普通单引号包裹函数体引号会层层叠加、难以阅读改用$$...$$或$function$...$function$这类带标签形式后函数体内部的单引号全部按字面处理。这也是美元引用被官方词法文档作为标准用法反复示范的场景。3. 程序化生成 SQL回到本篇开头提出的痛点当 SQL 由程序动态生成时美元引用让拼接变得可控。只要生成方与消费方约定了定界符$$或特定标签就无需逐字符处理内容中的单引号若内容本身还含$$则升级为带标签形式即可规避。这种约定定界符的思路与编程语言中字符串模板/原始字符串的设计目的一致。如何选择单引号转义还是美元引用场景单引号 转义美元引用$$/$tag$简单字符串写法最常规直接可用可用但显得重内容含单引号需写易错原样书写零转义程序化生成 SQL需按内容动态转义约定定界符更可控内容本身含$$无冲突需改用带标签形式$tag$需要表达语义无法表达标签可传达如$JSON$DO块 / 函数体引号叠加难维护标准做法总体原则临时调试的简单字面量用单引号即可凡是内容含引号、需要程序化拼装、或是书写DO块与函数体的场合优先考虑美元引用担心内容里出现$$时就用带标签的$tag$...$tag$定界。仓库延伸阅读本主题在 TIL 仓库的 PostgreSQL 分类下还有多篇相互印证的笔记可一并查阅postgres/escaping-a-quote-in-a-string.md单引号转义的最简演示postgres/two-ways-to-escape-a-quote-in-a-string.md双单引号与E前缀两种转义方式对比postgres/label-dollar-quoted-strings-with-a-tag.md带标签美元引用及 JSON 示例即本文第三部分的出处postgres/use-variables-in-an-anonymous-function.mddo $$...$$匿名块中的变量声明与流程控制实战。如果需要快速实践以上语法可在本地 psql 会话中直接逐条执行本文示例涉及jsonb转换的示例需要 PostgreSQL 支持该类型9.4 及以上版本均默认可用。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐PostgreSQL 带标签美元引用Tagged Dollar-Quoting优雅处理含 $$ 与 JSON 的字符串字面量PostgreSQL 带标签美元引用Tagged Dollar Quoting优雅处理含 $$ 与 JSON 的字符串字面量 本文围绕 PostgreSQ文档教程知识库TIL 实战PostgreSQL 字符串中单引号的两种转义方式双写引号与 E 转义字符串TIL 实战PostgreSQL 字符串中单引号的两种转义方式双写引号与 E 转义字符串 在 PostgreSQL 中字符串字面量必须用单引号 文档教程知识库Swift 字符串换行转义SE-0182用 \ 续行符优雅拆分超长字符串字面量Swift 字符串换行转义SE 0182用 \ 续行符优雅拆分超长字符串字面量 本篇文章围绕 Swift Evolution 提案 SE 0182Str文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表