string_escape 是 sql server 2016+ 提供的原生函数,专用于将字符串按 json 规则转义为合法字面量,自动处理双引号、控制字符、反斜杠及 unicode 控制符,确保手动拼接 json 时的安全性与合规性。

STRING_ESCAPE 是什么,它在 JSON 场景下能做什么?
STRING_ESCAPE 是 SQL Server 2016+ 引入的函数,专用于对字符串做特定格式的转义。当你要把任意文本拼进 JSON 字符串(比如用 FOR JSON 之外的手动拼接),而该文本里含双引号、换行、反斜杠等 JSON 非法字符时,STRING_ESCAPE 就是唯一原生可靠的转义手段。
它不生成完整 JSON,也不解析 JSON,只负责把输入字符串按 'json' 模式转义成合法 JSON 字符串字面量。比如把 "He said: "Hello"" 变成 "He said: "Hello""。
- 只接受两个参数:
STRING_ESCAPE(input_string, 'json'),第二个参数必须是字面量'json',不能是变量或表达式 - 输入为
NULL时返回NULL,不是空字符串 - 不处理编码问题(如 UTF-8 字节序列),只处理 Unicode 字符级别的 JSON 转义规则
- 对控制字符(如
CHAR(10)、CHAR(13))自动转为、,这是手动替换容易遗漏的点
什么时候必须用 STRING_ESCAPE,而不是 REPLACE 或 CONCAT?
手动用 REPLACE 处理双引号和反斜杠看似简单,但会漏掉三类关键字符:
- 换行符(
CHAR(10))、回车(CHAR(13))、制表符(CHAR(9)):JSON 标准禁止未转义的裸控制字符 - Unicode 控制字符(如
CHAR(1)到CHAR(31),不含空格):需转为uXXXX形式 - 已经带反斜杠的字符串(如 Windows 路径
C: empile.txt):双重转义风险(→\)
STRING_ESCAPE 一次性覆盖全部规则。例如:
SELECT STRING_ESCAPE('C: emp
"quote" & u2764', 'json');
结果是:"C: emp
"quote" & u2764" —— 自动处理了路径反斜杠、换行、双引号、Unicode 符号。
- 不要对已转义过的字符串重复调用
STRING_ESCAPE,否则"会变成\" - 不要把它和
FOR JSON混用:FOR JSON内部已自动转义,再套一层会导致双转义 - 若字段可能含
NULL,记得提前用ISNULL(col, '')或COALESCE处理,否则整条 JSON 拼接会变NULL
实际拼 JSON 时,STRING_ESCAPE 应该放在哪一层?
它只该用于「原始业务数据」到「JSON 字符串字面量」的转换环节,也就是最内层的值封装。典型错误是把它用在 key 名或顶层结构上。
正确做法:
- key 名必须是合法标识符(不用
STRING_ESCAPE),如'"name": '+ STRING_ESCAPE(name, 'json') +' - 数值、布尔、
NULL字面量不经过STRING_ESCAPE(它们不是字符串) - 嵌套 JSON 对象/数组应由
FOR JSON生成,或用STRING_ESCAPE处理其内部字符串字段后再拼接
示例(拼一个用户对象):
SELECT '{' +
'"id":' + CAST(id AS VARCHAR) + ',' +
'"name":' + STRING_ESCAPE(name, 'json') + ',' +
'"note":' + ISNULL(STRING_ESCAPE(note, 'json'), 'null') +
'}' AS json_fragment
FROM users
WHERE id = 123;
- 注意
note为NULL时,STRING_ESCAPE(NULL, 'json')返回NULL,所以用ISNULL(..., 'null')输出 JSON 的null字面量 -
CAST(id AS VARCHAR)不需要STRING_ESCAPE,因为数值本身无须转义
兼容性和性能要注意什么?
STRING_ESCAPE 在 SQL Server 2016 及以上可用,Azure SQL Database 全支持,但 Azure SQL Managed Instance 早期版本可能有补丁要求;SQL Server 2014 及更早完全不可用,别指望用 QUOTENAME 或自定义函数模拟 —— 它们无法处理 Unicode 控制字符。
性能上,它是标量函数,大数据量循环调用会有开销,但比客户端转义或 CLR 函数更轻量。若需高频生成 JSON,优先用 FOR JSON AUTO 或 FOR JSON PATH,仅在动态 key、混合结构等 FOR JSON 不支持的场景才手拼并依赖 STRING_ESCAPE。
- 不要试图用它转义整个 JSON 字符串(比如对
FOR JSON输出再套一层):既多余又破坏结构 - 它不校验输入是否为有效 UTF-16;若源数据含孤立代理项(lone surrogate),输出仍是无效 JSON —— 这类数据本身就有问题,得从前端或 ETL 清洗
真正容易被忽略的是:STRING_ESCAPE 对空字符串 '' 返回 '',但它不会帮你加外层引号。你拼 JSON 时,必须自己补上 ",否则 STRING_ESCAPE('abc', 'json') 得到的是 abc,不是 "abc"。











