3

У меня есть следующие функции:Почему SQL 2005 говорит, что этот UDF не является детерминированным?

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 должен быть детерминированным здесь, так как я использую его для целых чисел -> целых чисел.

Я полностью в тупике, любые идеи?

ответ

8

PARSENAME является недетерминированным, в целом. Да, вы используете его в контексте, который является детерминированным, но я предполагаю, что сервер этого не знает. Попробуйте заменить PARSENAME и посмотреть, не изменилось ли оно.

+0

MSDN заявляет, что PARSENAME всегда детерминирован – MicSim

+0

MicSim, я думаю, вы не пробовали его до голосования? –

+2

MicSim ... документы явно неверны. Возмутительно! – user53794

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 
0

Хм да так, что проблема заключается в использовании ParseName действительно. MSDN explicitly says детерминирован. Возможно, это потому, что SQL предполагает, что вы будете читать схему БД? Что бы предлагать недетерминированность, но я просто размышляю.