Azure SQL同版本服务器Split函数执行结果差异排查求助
问题根源:
ANSI_WARNINGS 服务器/数据库级配置差异 这个问题的核心是两台Azure SQL Server的 ANSI_WARNINGS 设置不一致导致的——尽管@@Version显示版本完全相同,但这个会话/服务器级别的配置会直接影响数据截断场景的行为。
为什么会出现差异?
先看你的Split函数定义:返回表的Value列类型是NVARCHAR(100),而当你用分隔符,去拆分一个全是分号分隔的字符串时,函数会把整个超长字符串(包含三个GUID的串,长度远超过100字符)作为单个值插入到@RtnValue表中。这时候:
- 当
ANSI_WARNINGS设置为 ON(默认配置):SQL Server会严格校验数据长度,发现要插入的字符串超出NVARCHAR(100)的限制,就会抛出Msg 8152截断错误,这就是第一台服务器的报错情况。 - 当
ANSI_WARNINGS设置为 OFF:SQL Server会静默截断超出长度的字符串,不会抛出任何错误,这就是第二台服务器无报错的原因。
验证与解决方法
- 检查当前配置:在两台服务器上分别执行以下语句,对比返回结果:
SELECT @@OPTIONS & 512 AS ANSI_WARNINGS_STATUS;
返回512表示ANSI_WARNINGS为ON,返回0表示为OFF。
- 临时会话级修改(仅用于测试):如果要在报错的服务器上模拟无报错行为,可以执行:
SET ANSI_WARNINGS OFF; -- 再执行你的测试语句 DECLARE @MyValues TABLE (MyKey uniqueidentifier not null) INSERT INTO @MyValues (MyKey) SELECT Value FROM [dbo].[split]('CAC71EA6-A78C-4D79-B868-8F9C44B0996D;B768F7D7-108D-46E6-88F8-404D53E08560;FA61D499-9FBA-4F66-94A0-2A11A416C30A',',') SELECT * FROM @MyValues MV
不过不建议长期关闭ANSI_WARNINGS,因为它会影响SQL的诸多核心行为(比如聚合函数处理NULL、除零错误提示等)。更合理的修复是修改Split函数的返回列长度,匹配输入参数的最大值,从根源避免截断:
ALTER FUNCTION [dbo].[Split] (@List NVARCHAR(4000), @SplitOn NVARCHAR(5)) RETURNS @RtnValue TABLE (Id INT identity(1, 1), Value NVARCHAR(4000)) -- 将长度改为4000 AS BEGIN WHILE (Charindex(@SplitOn, @List) > 0) BEGIN INSERT INTO @RtnValue (value) SELECT Value = ltrim(rtrim(Substring(@List, 1, Charindex(@SplitOn, @List) - 1))) SET @List = Substring(@List, Charindex(@SplitOn, @List) + len(@SplitOn), len(@List)) END INSERT INTO @RtnValue (Value) SELECT Value = ltrim(rtrim(@List)) RETURN END GO
补充说明
Azure SQL Server的ANSI_WARNINGS默认是ON,但可能通过服务器级配置变更、数据库级设置(执行ALTER DATABASE ... SET ANSI_WARNINGS ON/OFF)或者会话级语句覆盖导致差异。你可以通过以下语句查看数据库级的配置:
SELECT name, is_ansi_warnings_on FROM sys.databases WHERE name = '你的数据库名称';
内容的提问来源于stack exchange,提问作者DanielG
相关产品推荐
相关产品推荐

