尽管定义了 RETURN VARCHAR(10),但用户定义的函数仅返回第一个字符?

que*_*ion 5 sql-server t-sql functions sql-server-2019

每个人,

我无法弄清楚以下用户定义函数中缺少什么:

CREATE OR ALTER FUNCTION ufn_GetSalaryLevel(@Salary money)
RETURNS VARCHAR(10)
AS
BEGIN 
    IF (@Salary < 30000) RETURN 'Low';
    ELSE IF (@Salary <= 50000) RETURN 'Average';
    ELSE RETURN 'High';
    RETURN '';
END;

SELECT dbo.ufn_GetSalaryLevel(100440)
Run Code Online (Sandbox Code Playgroud)

输出仅包括“低”/“平均”/“高”返回值的第一个字符:

-----------------------------------------------------------------------
H

(1 row affected)
Run Code Online (Sandbox Code Playgroud)

为什么 MS SQL Server Management Studio 不考虑 VARCHAR(10)?

提前致谢!

Ps 请在下面找到我的输出 - 我不明白为什么它不能按预期工作?

在此处输入图片说明

ps2:该函数只有一个参数,我好像没有找到另一个同名的函数……下面可以找到与该函数相关的代码:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      <Author,,Name>
-- Create date: <Create Date, ,>
-- Description: <Description, ,>
-- =============================================
CREATE FUNCTION <Scalar_Function_Name, sysname, FunctionName> 
(
    -- Add the parameters for the function here
    <@Param1, sysname, @p1> <Data_Type_For_Param1, , int>
)
RETURNS <Function_Data_Type, ,int>
AS
BEGIN
    -- Declare the return variable here
    DECLARE <@ResultVar, sysname, @Result> <Function_Data_Type, ,int>

    -- Add the T-SQL statements to compute the return value here
    SELECT <@ResultVar, sysname, @Result> = <@Param1, sysname, @p1>

    -- Return the result of the function
    RETURN <@ResultVar, sysname, @Result>

END
GO
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

@@Version 结果

Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) 2019 年 9 月 24 日 13:48:23 版权所有 (C) 2019 Microsoft Corporation Express Edition(64 位),Windows 10 Enterprise 10.0(内部版本 18363:)150

Mar*_*ith 11

这是 2019 RTM 中 SQL Server 内联函数的一个错误。

DECLARE @Salary MONEY = 100440;
SELECT dbo.ufn_GetSalaryLevel(@Salary)
Run Code Online (Sandbox Code Playgroud)

常量扫描中的表达式(CONVERT_IMPLICIT更改CONVERT为使其可运行)是

SELECT CONVERT(VARCHAR(10), CASE
                              WHEN CASE
                                     WHEN CASE
                                            WHEN CONVERT(MONEY, @Salary, 0) < ( $30000.0000 )
                                              THEN ( 1 )
                                            ELSE ( 0 )
                                          END = ( 0 )
                                          AND CASE
                                                WHEN CONVERT(MONEY, @Salary, 0) <= ( $50000.0000 )
                                                  THEN ( 1 )
                                                ELSE ( 0 )
                                              END = ( 0 )
                                       THEN ( 1 )
                                     ELSE
                                       CASE
                                         WHEN CASE
                                                WHEN CONVERT(MONEY, @Salary, 0) < ( $30000.0000 )
                                                  THEN ( 1 )
                                                ELSE ( 0 )
                                              END = ( 0 )
                                              AND CASE
                                                    WHEN CONVERT(MONEY, @Salary, 0) <= ( $50000.0000 )
                                                      THEN ( 1 )
                                                    ELSE ( 0 )
                                                  END = ( 1 )
                                           THEN ( 1 )
                                         ELSE
                                           CASE
                                             WHEN CASE
                                                    WHEN CONVERT(MONEY, @Salary, 0) < ( $30000.0000 )
                                                      THEN ( 1 )
                                                    ELSE ( 0 )
                                                  END = ( 1 )
                                               THEN ( 1 )
                                             ELSE ( 0 )
                                           END
                                       END
                                   END = ( 0 )
                                THEN ''
                              ELSE CONVERT(VARCHAR(1), CASE
                                                         WHEN CASE
                                                                WHEN CONVERT(MONEY, @Salary, 0) < ( $30000.0000 )
                                                                  THEN ( 1 )
                                                                ELSE ( 0 )
                                                              END = ( 0 )
                                                              AND CASE
                                                                    WHEN CONVERT(MONEY, @Salary, 0) <= ( $50000.0000 )
                                                                      THEN ( 1 )
                                                                    ELSE ( 0 )
                                                                  END = ( 0 )
                                                              AND CASE
                                                                    WHEN CASE
                                                                           WHEN CONVERT(MONEY, @Salary, 0) < ( $30000.0000 )
                                                                             THEN ( 1 )
                                                                           ELSE ( 0 )
                                                                         END = ( 0 )
                                                                         AND CASE
                                                                               WHEN CONVERT(MONEY, @Salary, 0) <= ( $50000.0000 )
                                                                                 THEN ( 1 )
                                                                               ELSE ( 0 )
                                                                             END = ( 1 )
                                                                      THEN ( 1 )
                                                                    ELSE
                                                                      CASE
                                                                        WHEN CASE
                                                                               WHEN CONVERT(MONEY, @Salary, 0) < ( $30000.0000 )
                                                                                 THEN ( 1 )
                                                                               ELSE ( 0 )
                                                                             END = ( 1 )
                                                                          THEN ( 1 )
                                                                        ELSE ( 0 )
                                                                      END
                                                                  END = ( 0 )
                                                           THEN 'High'
                                                         ELSE CONVERT(VARCHAR(4), CASE
                                                                                    WHEN CASE
                                                                                           WHEN CONVERT(MONEY, @Salary, 0) < ( $30000.0000 )
                                                                                             THEN ( 1 )
                                                                                           ELSE ( 0 )
                                                                                         END = ( 0 )
                                                                                         AND CASE
                                                                                               WHEN CONVERT(MONEY, @Salary, 0) <= ( $50000.0000 )
                                                                                                 THEN ( 1 )
                                                                                               ELSE ( 0 )
                                                                                             END = ( 1 )
                                                                                         AND CASE
                                                                                               WHEN CASE
                                                                                                      WHEN CONVERT(MONEY, @Salary, 0) < ( $30000.0000 )
                                                                                                        THEN ( 1 )
                                                                                                      ELSE ( 0 )
                                                                                                    END = ( 1 )
                                                                                                 THEN ( 1 )
                                                                                               ELSE ( 0 )
                                                                                             END = ( 0 )
                                                                                      THEN 'Average'
                                                                                    ELSE CONVERT(VARCHAR(7), CASE
                                                                                                               WHEN CASE
                                                                                                                      WHEN CONVERT(MONEY, @Salary, 0) < ( $30000.0000 )
                                                                                                                        THEN ( 1 )
                                                                                                                      ELSE ( 0 )
                                                                                                                    END = ( 1 )
                                                                                                                 THEN 'Low'
                                                                                                               ELSE NULL
                                                                                                             END, 0)
                                                                                  END, 0)
                                                       END, 0)
                            END, 0) 
Run Code Online (Sandbox Code Playgroud)

带有文字的分支High有一个CONVERT(VARCHAR(1)截断它。

禁用该函数的内联

CREATE OR ALTER FUNCTION ufn_GetSalaryLevel(@Salary money)
RETURNS VARCHAR(10)
WITH INLINE=OFF
AS
Run Code Online (Sandbox Code Playgroud)
  • 或安装最新的 CU 来解决这个问题

  • 或将函数中的所有字符串文字VARCHAR(10)强制转换为显式(这varchar(1)是由于RETURN ''

  • 或重写函数以减少程序化。由inling产生的表达是在原始代码中相当复杂,并与下面简单得多(它能够恒定倍dbo.ufn_GetSalaryLevel(100440)'High'在编译时间)。

    CREATE OR ALTER FUNCTION ufn_GetSalaryLevel(@Salary money)
    RETURNS VARCHAR(10) AS
    BEGIN
    RETURN CASE
             WHEN @Salary < 30000
               THEN 'Low'
             WHEN @Salary <= 50000
               THEN 'Average'
             ELSE 'High'
           END;
    
    END;
Run Code Online (Sandbox Code Playgroud)