我有以下功能:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[IP4toBIGINT](
@ip4 varchar(15)
)
RETURNS bigint
WITH SCHEMABINDING
AS
BEGIN
-- oc3 oc2 oc1 oc0
-- 255.255.255.255
-- Declared as BIGINTs to avoid overflows when multiplying later on DECLARE @oct0 bigint, @oct1 bigint, @oct2 bigint, @oct3 bigint;
DECLARE @Result bigint;
SET @oct3 = CAST(PARSENAME(@ip4, 4) as tinyint);
SET @oct2 = CAST(PARSENAME(@ip4, 3) as tinyint);
SET @oct1 = CAST(PARSENAME(@ip4, 2) as tinyint);
SET @oct0 = CAST(PARSENAME(@ip4, 1) as tinyint);
-- Combine all values, multiply by 2^8, 2^16, 2^24 to bitshift.
SET @Result = @oct3 * 16777216 + @oct2 * 65536 + @oct1 * 256 + @oct0;
RETURN @Result;
END
但是...
SELECT
OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'IsDeterministic') as IsDeterministic
,OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'IsPrecise') as IsPrecise
,OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'IsSystemVerified') as IsSystemVerified
,OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'SystemDataAccess') as SystemDataAccess
,OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'UserDataAccess') as UserDataAccess
返回(结果转置):
IsDeterministic 0
IsPrecise 1
IsSystemVerified 1
SystemDataAccess 0
UserDataAccess 0
我尝试多次删除并重新创建该函数,以确保它不是一些缓存问题。 CAST在这里应该是确定性的,因为我将它用于字符串 - >整数。
我完全难过,有什么想法吗?
答案 0 :(得分:8)
PARSENAME总的来说是不确定的。是的,您在确定性的上下文中使用它,但我猜测服务器不知道。尝试替换PARSENAME并查看它是否发生变化。
答案 1 :(得分:3)
这是造成问题的PARSENAME。用硬编码字符串替换它会导致确定性。不知道为什么...解析名称应该只是一个奇特的分裂函数。
检查出来:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[IP4toBIGINT](
@ip4 varchar(15)
)
RETURNS bigint
WITH SCHEMABINDING
AS
BEGIN
-- oc3 oc2 oc1 oc0
-- 255.255.255.255
-- Declared as BIGINTs to avoid overflows when multiplying later on
DECLARE @oct0 bigint, @oct1 bigint, @oct2 bigint, @oct3 bigint;
DECLARE @Result bigint;
SET @oct3 = CAST('1' as tinyint);
SET @oct2 = CAST('2' as tinyint);
SET @oct1 = CAST('3' as tinyint);
SET @oct0 = CAST('4' as tinyint);
-- Combine all values, multiply by 2^8, 2^16, 2^24 to bitshift.
SET @Result = @oct3 * 16777216 + @oct2 * 65536 + @oct1 * 256 + @oct0
RETURN @Result
END
GO
SELECT
OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'IsDeterministic') as IsDeterministic
,OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'IsPrecise') as IsPrecise
,OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'IsSystemVerified') as IsSystemVerified
,OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'SystemDataAccess') as SystemDataAccess
,OBJECTPROPERTYEX(OBJECT_ID('dbo.IP4toBIGINT'), 'UserDataAccess') as UserDataAccess
结果:
IsDeterministic IsPrecise IsSystemVerified SystemDataAccess UserDataAccess
1 1 1 0 0
答案 2 :(得分:0)
是的,问题是确实使用了PARSENAME。 MSDN explicitly says这是确定性的。也许这是因为SQL假设您将阅读数据库架构?这表明非决定论,但我只是在推测。