2014-06-16 1 views
1

Pourquoi SQL Server pense-t-il que cette fonction est non déterministe?Pourquoi cette fonction est-elle non déterministe?

CREATE FUNCTION [Util].[BuildStreetFullName] 
(
    @StreetNumber VARCHAR(20), 
    @StreetDir VARCHAR(2), 
    @StreetName VARCHAR(50) , 
    @StreetType VARCHAR(4) , 
    @StreetPostDir VARCHAR(2) 
) 
RETURNS VarChar(100) 
AS 
BEGIN 
    SET @StreetNumber = NULLIF(Util.Trim(@StreetNumber ), ''); 
    SET @StreetDir  = NULLIF(Util.Trim(@StreetDir  ), ''); 
    SET @StreetName  = NULLIF(Util.Trim(@StreetName ), ''); 
    SET @StreetType  = NULLIF(Util.Trim(@StreetType ), ''); 
    SET @StreetPostDir = NULLIF(Util.Trim(@StreetPostDir ), ''); 

    DECLARE @Result VarChar(100) = @StreetNumber; 

    IF @StreetDir IS NOT NULL BEGIN 
     IF @Result IS NOT NULL 
      SET @Result = @Result + ' ' + @StreetDir; 
     ELSE 
      SET @Result = @StreetDir; 
    END 

    IF @StreetName IS NOT NULL BEGIN 
     IF @Result IS NOT NULL 
      SET @Result = @Result + ' ' + @StreetName; 
     ELSE 
      SET @Result = @StreetName; 
    END 


    IF @StreetType IS NOT NULL BEGIN 
     IF @Result IS NOT NULL 
      SET @Result = @Result + ' ' + @StreetType; 
     ELSE 
      SET @Result = @StreetType; 
    END 

    IF @StreetPostDir IS NOT NULL BEGIN 
     IF @Result IS NOT NULL 
      SET @Result = @Result + ' ' + @StreetPostDir; 
     ELSE 
      SET @Result = @StreetPostDir; 
    END 

    RETURN NULLIF(@Result, ''); 
END 

CREATE FUNCTION [Util].[Trim] 
(
    @value nVarChar(max) 
) 
RETURNS nVarChar(max) 
AS 
BEGIN 
    RETURN LTrim(RTrim(@value)) 
END 
+0

Quelle est la plus petite fonction dervied que SQL Server dit est ND de cela? (Autrement dit, cela ne semble pas être un cas de test minimal.) – user2864740

+0

@ypercube Oui, c'est juste une faute de frappe. Je sais mieux. –

+0

@billinkc Non, c'est juste un wrapper autour de LTrim (RTim (value)). Si vous faites défiler vers le bas, vous pouvez le voir. –

Répondre

3

1) Vous pouvez créer à la fois la fonction WITH SCHEMABINDING:

ALTER FUNCTION dbo.[Trim] 
(
    @value nVarChar(max) 
) 
RETURNS nVarChar(max) 
WITH SCHEMABINDING 
AS 
... 

et

ALTER FUNCTION dbo.[BuildStreetFullName] 
(
    @StreetNumber VARCHAR(20), 
    @StreetDir VARCHAR(2), 
    @StreetName VARCHAR(50) , 
    @StreetType VARCHAR(4) , 
    @StreetPostDir VARCHAR(2) 
) 
RETURNS VarChar(100) 
WITH SCHEMABINDING 
AS 
... 

Cela forcera SQL Server pour vérifier si ces fonctions sont déterministes ou non.

SELECT OBJECTPROPERTY(OBJECT_ID(N'dbo.[BuildStreetFullName]') , 'IsDeterministic') AS IsDeterministic 

Sortie:

IsDeterministic 
--------------- 
1 

2) S'il vous plaît ne pas utiliser != NULL opérateur pour vérifier NOT NULL. Utilisez IS NOT NULL. À ce moment ANSI_NULLS OFF est obsolète et une future version de SQL Server autorisera seulement ANSI_NULLS ON.

3) Les fonctions scalaires peuvent être un cauchemar du point de vue de la performance. Je voudrais réécrire ces fonctions comme inline table valued functions.

+1

Intéressant. Je n'ai rien vu dans la documentation à l'appui, mais cela fonctionne. –

+1

Le point trois est devenu légèrement perdu * en traduction *. Je pense que vous proposez 'scalar multi-statement' =>' table-valued inline'. – MatBailie

+0

En ce qui concerne les fonctions inline, je les ai testées dans SQL Server 2014 en utilisant Util.Trim comme cas de base. Selon le plan d'exécution de la requête, il n'y a pas de différence de coût. Peut-être que l'utilisation de INLINE n'est plus un problème de performance pour les fonctions scalaires. –

Questions connexes