Почему SQL 2005 говорит, что эта UDF недетерминирована? - PullRequest
3 голосов
/ 20 февраля 2009

У меня есть следующая функция:

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

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

Ответы [ 3 ]

8 голосов
/ 20 февраля 2009

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

3 голосов
/ 20 февраля 2009

Это 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 голосов
/ 21 февраля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...