使用STRING_SPLIT报错‘Invalid object name’,如何正确拆分字符串并循环遍历?
解决SQL Server字符串拆分与循环遍历的问题
首先,你遇到的STRING_SPLIT报错,大概率是因为你的SQL Server版本低于2016,或者数据库的兼容性级别设置低于130——这个函数是从SQL Server 2016才开始引入的,而且需要数据库兼容性级别至少130才能正常调用。下面分两种场景给你具体解决方案:
场景一:SQL Server版本≥2016,且兼容性级别符合要求
先确认数据库兼容性级别是否达标,执行这条命令检查:
SELECT name, compatibility_level FROM sys.databases WHERE name = '你的数据库名';
如果兼容性级别低于130,执行这条命令修改(根据你的SQL Server版本,也可以设为140、150等更高级别):
ALTER DATABASE 你的数据库名 SET COMPATIBILITY_LEVEL = 130;
确认没问题后,拆分+遍历有两种常用方式,优先推荐基于集合的操作(SQL是集合型语言,游标性能较差):
方式1:基于集合的直接操作(推荐)
不需要显式循环,直接对拆分后的结果集做业务处理,比如:
DECLARE @columnCamera varchar(MAX) = 'aaa,bbb,ccc'; -- 直接读取拆分后的每一项,也可以在这里插入临时表、执行业务逻辑 SELECT value AS 拆分后的列 FROM STRING_SPLIT(@columnCamera, ',') -- 示例:如果要过滤空值,可以加WHERE value <> ''
方式2:游标循环(仅当必须逐行执行特定逻辑时使用)
DECLARE @columnCamera varchar(MAX) = 'aaa,bbb,ccc'; DECLARE @currentItem varchar(MAX); -- 声明游标指向拆分后的结果 DECLARE itemCursor CURSOR FOR SELECT value FROM STRING_SPLIT(@columnCamera, ','); -- 打开游标并读取第一条数据 OPEN itemCursor; FETCH NEXT FROM itemCursor INTO @currentItem; -- 循环处理每一项 WHILE @@FETCH_STATUS = 0 BEGIN -- 这里替换成你的业务逻辑,比如打印、调用存储过程等 PRINT '正在处理:' + @currentItem; -- 读取下一条数据 FETCH NEXT FROM itemCursor INTO @currentItem; END; -- 关闭并释放游标 CLOSE itemCursor; DEALLOCATE itemCursor;
场景二:SQL Server版本低于2016(无法使用STRING_SPLIT)
这种情况下,你可以选择自定义拆分函数,或者用XML临时拆分:
方式1:自定义字符串拆分函数
先创建一个可复用的拆分函数:
CREATE FUNCTION dbo.SplitString ( @InputString NVARCHAR(MAX), @Delimiter NVARCHAR(50) ) RETURNS @OutputTable TABLE (Value NVARCHAR(MAX)) AS BEGIN DECLARE @StartIndex INT, @EndIndex INT; SET @StartIndex = 1; -- 确保字符串末尾有分隔符,避免遗漏最后一项 IF SUBSTRING(@InputString, LEN(@InputString) - LEN(@Delimiter) + 1, LEN(@Delimiter)) <> @Delimiter BEGIN SET @InputString = @InputString + @Delimiter; END; WHILE CHARINDEX(@Delimiter, @InputString) > 0 BEGIN SET @EndIndex = CHARINDEX(@Delimiter, @InputString); INSERT INTO @OutputTable(Value) SELECT SUBSTRING(@InputString, @StartIndex, @EndIndex - @StartIndex); SET @InputString = SUBSTRING(@InputString, @EndIndex + LEN(@Delimiter), LEN(@InputString)); END; RETURN; END;
之后用法和STRING_SPLIT完全一致:
DECLARE @columnCamera varchar(MAX) = 'aaa,bbb,ccc'; -- 基于集合操作 SELECT Value FROM dbo.SplitString(@columnCamera, ','); -- 游标循环的话,把STRING_SPLIT替换成dbo.SplitString即可,代码和场景一的游标示例一致
方式2:XML临时拆分(无需创建函数)
如果不想创建函数,可以用XML临时处理:
DECLARE @columnCamera varchar(MAX) = 'aaa,bbb,ccc'; DECLARE @xml XML; -- 将字符串转成XML格式 SET @xml = CAST('<root><item>' + REPLACE(@columnCamera, ',', '</item><item>') + '</item></root>' AS XML); -- 提取拆分后的每一项 SELECT T.c.value('.', 'VARCHAR(MAX)') AS Value FROM @xml.nodes('/root/item') T(c);
这个结果集同样可以用于游标循环或直接业务操作。
最后提醒:除非业务逻辑必须逐行处理,否则尽量避免使用游标——集合操作的性能远高于游标,更符合SQL的设计理念。
内容的提问来源于stack exchange,提问作者user979331
相关产品推荐
相关产品推荐

