在关系型数据库里处理半结构化数据时,经常需要确认某个字段里的字符串到底是不是规范的JSON。SQL Server从2016版本开始提供了ISJSON函数,它能在T-SQL里直接完成语法层面的校验,不需要把数据拉到应用代码里再解析。理解这个函数的返回规则和使用限制,可以帮助我们设计更稳的数据表结构。

ISJSON函数的基本用法
ISJSON是SQL Server内置的标量函数,接收一段字符串表达式,按照JSON标准判断其语法是否合法。它的返回值只有三种情况:当输入字符串符合JSON规范时返回1;当不符合时返回0;当输入为NULL时返回NULL。这种三元结果让它在条件判断里非常直观,比如在WHERE子句里直接过滤掉非法记录。
下面是一个最简单的调用示例,演示如何对常量字符串做校验:
DECLARE @txt NVARCHAR(MAX) = N'{"name":"张三","age":28}';
SELECT ISJSON(@txt) AS result; -- 返回 1
SET @txt = N'{name:张三}'; -- 缺少双引号的键名,不合法
SELECT ISJSON(@txt) AS result; -- 返回 0
SET @txt = NULL;
SELECT ISJSON(@txt) AS result; -- 返回 NULL
从示例可以看到,ISJSON只做语法检查,不关心JSON里的业务含义。例如数字类型写成字符串、数组里混用类型,这些都不会导致返回0,只要整体结构符合JSON文法即可。这一点在后续设计校验逻辑时要特别注意。
利用CHECK约束保证字段只能是JSON
如果某张表的某一列专门用来存JSON文本,最省心的做法是把ISJSON写进列的CHECK约束里。这样任何插入或更新操作,只要字符串通不过ISJSON校验,数据库就会直接报错并拒绝写入,非法数据根本进不了表。
以下建表语句演示了这种约束方式:
CREATE TABLE order_ext (
id INT PRIMARY KEY,
ext_info NVARCHAR(MAX) NOT NULL
CONSTRAINT ck_ext_info_json CHECK (ISJSON(ext_info) = 1)
);
-- 合法插入
INSERT INTO order_ext(id, ext_info)
VALUES (1, N'{"coupon":"A12","vip":true}');
-- 非法插入,会被CHECK约束拦截
INSERT INTO order_ext(id, ext_info)
VALUES (2, N'{coupon:A12}');
使用CHECK加ISJSON的好处是校验逻辑下沉到数据库层,不论数据来自哪个应用、哪次批量导入,都能保持统一标准。不过也要注意,NVARCHAR类型更适合存JSON,因为SQL Server的JSON函数对Unicode支持更好,避免出现乱码或解析异常。
与其他数据库的对照
并不是所有关系数据库都叫ISJSON。MySQL里可以用JSON_VALID函数达到类似效果,PostgreSQL则通常直接用json类型字段,插入非法串会自然报错。如果项目需要跨库兼容,就要针对具体数据库选择对应的校验函数,不能假定所有环境都有ISJSON。
下面是MySQL里的等价写法:
SELECT JSON_VALID('{"a":1}'); -- 返回 1
SELECT JSON_VALID('{a:1}'); -- 返回 0
在跨库迁移脚本时,建议把JSON校验封装成一个可替换的函数或视图,减少业务SQL里对特定函数名的耦合。这样后续换数据库,只需要改底层校验实现,上层查询逻辑可以保持不变。
常见误用与注意点
有人会以为ISJSON能顺带验证JSON里某个字段是否存在或者类型对不对,其实它只管语法骨架。比如字符串写成了JSON数组而不是对象,ISJSON照样返回1。如果需要更细的内容校验,还要配合JSON_VALUE、JSON_QUERY等函数进一步抽取和判断。
另一个容易踩的坑是对空字符串的处理。在SQL Server里,空字符串N''不是NULL,ISJSON(N'')会返回0,因为空串不是合法JSON。如果业务上允许“无数据”状态,应该明确用NULL而不是空串来存储,否则CHECK约束会把它当成非法JSON挡住。
SELECT ISJSON(N'') AS empty_str; -- 0 SELECT ISJSON(NULL) AS null_val; -- NULL
综合来看,ISJSON适合做第一道门槛,把明显拼错的文本挡在门外;复杂的业务规则校验还是放在应用层或存储过程里更灵活。把两者结合起来,既能利用数据库的内建效率,又不丢失对数据语义的掌控。
SQLISJSONJSON_validation修改时间:2026-08-07 08:34:06