3

J'ai la fonction suivante:Pourquoi SQL 2005 dit-il que cette fonction UDF est non-déterministe?

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 

Mais ...

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 

Returns (résultat transposé):

IsDeterministic 0

IsPrecise 1

IsSystemVerified 1

SystemDataAccess 0

UserDataAccess 0

J'ai essayé de recréer et de laisser tomber la fonction à plusieurs reprises pour vous assurer qu'il est pas un problème de mise en cache. CAST devrait être déterministe ici puisque je l'utilise pour les chaînes-> entiers.

Je suis complètement perplexe, des idées?

Répondre

8

PARSENAME est globalement non déterministe. Oui, vous l'utilisez dans un contexte déterministe, mais je suppose que le serveur ne le sait pas. Essayez de remplacer PARSENAME et voyez si cela change.

+0

MSDN indique que PARSENAME est toujours déterministe – MicSim

+0

MicSim, je suppose que vous ne l'avez pas essayé avant de voter? –

+2

MicSim ... les documents sont clairement incorrects. Choquant! – user53794

3

C'est le PARSENAME qui cause des problèmes. Le remplacer par une chaîne codée en dur entraîne un déterminisme. Aucune idée pourquoi ... analyser le nom est censé être une simple fonction de split.

Check this out:

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 

Résultats:

IsDeterministic IsPrecise IsSystemVerified SystemDataAccess UserDataAccess 
1    1   1     0    0 
0

Hmm oui si le problème est l'utilisation de ParseName en effet. MSDN explicitly says il est déterministe. Peut-être est-ce parce que SQL suppose que vous allez lire le schéma DB? Ce qui suggère un non-déterminisme, mais je ne fais que spéculer.

Questions connexes