求T-SQL中QUOTENAME()的幂等实现,支持安全嵌套调用
实现幂等版QUOTENAME()以支持嵌套调用
当然有办法实现一个支持嵌套调用的幂等版QUOTENAME()!原生QUOTENAME()的问题在于它不会检查输入是否已经被正确引用,所以每次调用都会无脑添加分隔符,导致嵌套调用时出现重复包裹的情况(比如[[simple_name]])。我们需要的是一个幂等的版本——不管调用多少次,结果都和只调用一次完全相同。
核心思路
先检查输入是否已经是符合T-SQL规范的带引号标识符:
- 对于默认的方括号分隔符:输入必须以
[开头、]结尾,且内部所有的[都已经转义为]](这是原生QUOTENAME()的转义规则)。 - 对于双引号分隔符:输入必须以
"开头、"结尾,且内部所有的"都转义为""。
如果输入已经符合规范,直接返回;否则调用原生QUOTENAME()处理。
自定义幂等函数代码
CREATE OR ALTER FUNCTION dbo.IdempotentQuotename( @input NVARCHAR(128), @quoteChar NCHAR(1) = N'[' ) RETURNS NVARCHAR(258) AS BEGIN -- 处理方括号分隔符的情况 IF @quoteChar = N'[' BEGIN -- 验证是否已被正确引用:首尾为[],且内部的[都已转义为]] IF LEN(@input) >= 2 AND LEFT(@input, 1) = N'[' AND RIGHT(@input, 1) = N']' AND NOT EXISTS ( SELECT 1 FROM STRING_SPLIT(@input, N']') WHERE LEN(value) > 0 AND RIGHT(value, 1) <> N'[' ) BEGIN RETURN @input; END ELSE BEGIN RETURN QUOTENAME(@input, @quoteChar); END END -- 处理双引号分隔符的情况 ELSE IF @quoteChar = N'"' BEGIN IF LEN(@input) >= 2 AND LEFT(@input, 1) = N'"' AND RIGHT(@input, 1) = N'"' AND NOT EXISTS ( SELECT 1 FROM STRING_SPLIT(@input, N'"') WHERE LEN(value) > 0 AND RIGHT(value, 1) <> N'"' ) BEGIN RETURN @input; END ELSE BEGIN RETURN QUOTENAME(@input, @quoteChar); END END -- 其他分隔符直接调用原生函数(如需支持可扩展逻辑) ELSE BEGIN RETURN QUOTENAME(@input, @quoteChar); END END GO
测试效果
我们来验证一下嵌套调用的表现:
DECLARE @name NVARCHAR(128) = N'simple_name'; DECLARE @quotedName NVARCHAR(258) = dbo.IdempotentQuotename(@name); SELECT @name AS [Original Name], dbo.IdempotentQuotename(@name) AS [First Call], dbo.IdempotentQuotename(@quotedName) AS [Nested Call], dbo.IdempotentQuotename(dbo.IdempotentQuotename(@quotedName)) AS [Double Nested Call];
执行结果会是:
| Original Name | First Call | Nested Call | Double Nested Call |
|---|---|---|---|
| simple_name | [simple_name] | [simple_name] | [simple_name] |
甚至对于包含特殊字符的名称,比如table[with]brackets,测试结果也符合预期:
DECLARE @specialName NVARCHAR(128) = N'table[with]brackets'; SELECT dbo.IdempotentQuotename(@specialName) AS [First Call], dbo.IdempotentQuotename(dbo.IdempotentQuotename(@specialName)) AS [Nested Call];
结果:
| First Call | Nested Call |
|---|---|
| [table[]with]]brackets] | [table[]with]]brackets] |
注意事项
- 函数保持了和原生
QUOTENAME()一致的输入输出长度限制(输入NVARCHAR(128),输出NVARCHAR(258)),避免溢出问题。 - 目前支持方括号和双引号两种最常用的分隔符,如果需要支持其他分隔符,可以扩展对应的检查逻辑。
- 如果你不想创建自定义函数,也可以在每次调用前手动做类似的检查,但函数的方式更便于在代码库中统一复用。
内容的提问来源于stack exchange,提问作者Karl Kieninger
相关产品推荐
相关产品推荐

