如何在SQL中实现类似C# nameof的变量名获取及避免JSON路径拼写错误
我希望在SQL中实现类似C#里nameof(variable)的获取变量名功能。在SQL存储过程中,我处理一个名为@MetaData的变量,它是一个预定义结构的JSON字符串:
{ "Somekey1": "Somevalue1", "Somekey2": "Somevalue2" }
在存储过程中,我会检查Somekey1是否存在并执行相应操作:
DECLARE @existingSomekey1 VARCHAR(100) = (SELECT [value] FROM OPENJSON(@Metadata) WHERE [key] = 'Somekey1')
之后我会执行如下操作:
SET @Somekey1 = 'Some new value 1' SELECT JSON_MODIFY(@Metadata, '$.Somekey1', @Somekey1)
问题在于,如果JSON_MODIFY中的路径(与变量名一致)拼写错误,会错误创建新属性。请问避免此类拼写错误的最佳实践是什么?
以下是几种避免JSON路径拼写错误的实用方案:
使用常量统一管理JSON键名
将JSON中的固定键名定义为变量常量,所有需要引用键名的地方都使用这个常量,彻底避免硬编码字符串的拼写错误。示例:-- 定义键名常量 DECLARE @KEY_SOMEKEY1 NVARCHAR(50) = 'Somekey1' -- 查询键值时引用常量 DECLARE @existingSomekey1 VARCHAR(100) = (SELECT [value] FROM OPENJSON(@Metadata) WHERE [key] = @KEY_SOMEKEY1) -- 修改JSON时动态生成路径 SET @Somekey1 = 'Some new value 1' SELECT JSON_MODIFY(@Metadata, CONCAT('$.', @KEY_SOMEKEY1), @Somekey1)后续如果键名需要变更,只需修改常量定义,所有引用处自动同步,大幅降低维护成本。
先校验键存在性再执行修改
在调用JSON_MODIFY前,先检查目标键是否存在于原JSON中,不存在则跳过修改或抛出错误,从源头避免创建非预期的新属性:SET @Somekey1 = 'Some new value 1' -- 检查目标键是否存在 DECLARE @keyExists BIT = (SELECT CASE WHEN EXISTS( SELECT 1 FROM OPENJSON(@Metadata) WHERE [key] = 'Somekey1' ) THEN 1 ELSE 0 END) IF @keyExists = 1 SELECT JSON_MODIFY(@Metadata, '$.Somekey1', @Somekey1) ELSE -- 可根据业务需求选择抛出错误或返回原JSON THROW 50001, '目标键不存在,无法执行修改操作', 1;用JSON Schema验证约束结构
若使用SQL Server 2016及以上版本,可以通过JSON_SCHEMA_VALIDATE函数定义JSON的合法结构,禁止新增未定义的属性。修改后验证JSON结构,一旦出现拼写错误导致的非法属性,会直接触发验证失败:-- 定义JSON结构约束Schema DECLARE @jsonSchema NVARCHAR(MAX) = N'{ "type": "object", "properties": { "Somekey1": {"type": "string"}, "Somekey2": {"type": "string"} }, "additionalProperties": false }' -- 执行JSON修改 SET @Metadata = JSON_MODIFY(@Metadata, '$.Somekey1', @Somekey1) -- 验证修改后的JSON是否符合结构 IF JSON_SCHEMA_VALIDATE(@jsonSchema, @Metadata) = 0 THROW 50002, 'JSON结构不符合预期,存在非法属性', 1;其中
additionalProperties: false配置会严格禁止Schema中未定义的属性,从结构层面杜绝错误拼写带来的问题。封装JSON操作到专用存储过程
将JSON的读取、修改等操作封装到专用存储过程中,集中处理键名校验和路径生成,减少业务逻辑中重复硬编码的场景。例如创建UpdateJsonProperty存储过程,接收JSON字符串、键名、新值作为参数,内部统一完成存在性校验和修改操作,确保所有调用方的逻辑一致且无拼写错误。
内容的提问来源于stack exchange,提问作者Ahmad Masalha

