为什么这个函数不确定?

时间:2014-06-16 19:02:37

标签: sql-server sql-server-2014

为什么SQL Server认为此函数是非确定性的?

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

1 个答案:

答案 0 :(得分:3)

1)您可以创建函数WITH SCHEMABINDING

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

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
...

这将强制SQL Server检查这些功能是否具有确定性。

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

输出:

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

2)请不要使用!= NULL运算符来检查NOT NULL。使用IS NOT NULL。目前,ANSI_NULLS OFF已弃用,SQL Server的未来版本仅允许ANSI_NULLS ON

3)从性能的角度来看,标量函数可能是一场噩梦。我会重写这些函数为inline table valued functions