STUFF函数是SQL Server特有字符串操作函数,语法为STUFF(string, start, length, replacement),其中start从1开始计数,length为删除字符数(可为0),start或length为负/0时返回NULL,超长则删至末尾。

STUFF函数在SQL Server中怎么用
STUFF只存在于SQL Server(及Azure SQL),MySQL、PostgreSQL、Oracle都不支持。它不是通用字符串替换函数,而是「删除+插入」的组合操作:从指定位置删掉指定长度的字符,再把新字符串插进去。
语法是 STUFF(string, start, length, replacement),四个参数缺一不可:
-
string:原字符串,可以是列名或字面量 -
start:起始位置,从1开始计数(不是0);若为0或负数,结果为NULL -
length:要删除的字符数;若为负数,结果为NULL;若超过剩余长度,就删到末尾 -
replacement:插入的新字符串,可以为空字符串''
例如:STUFF('abcdef', 3, 2, 'XY') → 先删掉第3位起的2个字符(即'cd'),再插入'XY',结果是'abXYef'。
想替换固定位置的字符,但长度不确定怎么办
STUFF不识别模式,只认位置和长度。如果目标位置不固定(比如“把第二个下划线后的3个字符换成***”),就不能直接用STUFF——得先用CHARINDEX或PATINDEX算出位置,再套进STUFF里。
常见错误是硬编码start值,结果在数据格式稍有变化时全部错位。稳妥做法是嵌套定位函数:
SELECT STUFF(
column_name,
CHARINDEX('_', column_name, CHARINDEX('_', column_name) + 1) + 1,
3,
'***'
) FROM table_name;
这段代码找第二个下划线的位置,再+1跳过它,作为start;删3个字符,替换成'***'。注意CHARINDEX没找到时返回0,会导致STUFF第一个参数为NULL,整个结果变NULL——实际使用前建议加ISNULL或CASE WHEN兜底。
和REPLACE函数混淆导致逻辑错误
很多人想“替换某个子串”,却误用STUFF,结果发现行为完全不对。比如想把所有'old'换成'new',写成STUFF(col, CHARINDEX('old', col), 3, 'new')——这只会替换第一个匹配项,且要求'old'必须存在;而REPLACE(col, 'old', 'new')才是全量、安全、无位置依赖的替换。
STUFF适用场景很窄:你明确知道要动的是第N个字符起的M个字符,且这个位置在所有行中相对稳定。典型例子包括:
- 身份证号脱敏:隐藏第9–14位 →
STUFF(id_card, 9, 6, '******') - 固定格式订单号补位:把第5位起的2个字符强制设为
'00' - 截断并拼接路径:删掉扩展名再加
'.bak'(需配合LEN和REVERSE定位)
NULL、空字符串和Unicode带来的坑
STUFF对NULL极其敏感:string为NULL,或start/length算出来是NULL/负数/0,整个结果就是NULL。别指望它自动跳过或报错提示。
另一个容易忽略的是Unicode:如果字段是NVARCHAR,但replacement用了普通字符串字面量(如'abc'),SQL Server会隐式转换,可能引发排序规则冲突或截断。稳妥写法是显式加N前缀:N'abc'。
还有性能问题:在WHERE条件里对列用STUFF(比如WHERE STUFF(name, 1, 1, '') = 'ohn')会导致索引失效,全表扫描。这种需求应提前计算好值存入计算列,或改用其他可SARGable的方式。
真正要用STUFF的时候,往往意味着业务规则和数据格式高度固化。一旦格式松动,修复成本比一开始选错函数还高。

















