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)