SQL函数不能按我想要的方式工作

时间:2017-12-04 12:52:01

标签: sql sql-server sql-server-2017

我写了这两个函数:

USE muziekdatabase
GO
CREATE FUNCTION fnSpecNivAantal
    (
        @Niveau as char(1)
    )

RETURNS char(1)
AS 

BEGIN

    DECLARE @Aantal AS int

    IF @Niveau = 'A'
    SET @Aantal = (SELECT COUNT(*) FROM STUK WHERE niveaucode = 'A')

    ELSE IF @Niveau = 'B' 
    SET @Aantal = (SELECT COUNT(*) FROM STUK WHERE niveaucode = 'B')

    ELSE IF @Niveau = 'C'
    SET @Aantal = (SELECT COUNT(*) FROM STUK WHERE niveaucode = 'C')

RETURN @Aantal

END

USE muziekdatabase
GO

ALTER FUNCTION fnHoogsteNummer 
    (
        @EersteNummer as numeric,
        @TweedeNummer as numeric
    )
RETURNS numeric 
AS 
BEGIN

    DECLARE @HoogsteNummer as VARCHAR(MAX)

    IF MAX(@Eerstenummer) > MAX(@TweedeNummer)
    SET @HoogsteNummer = @EersteNummer
    ELSE IF
    MAX(@Tweedenummer) > MAX(@Eerstenummer)
    SET @HoogsteNummer = @TweedeNummer
    ELSE IF
    @EersteNummer = @TweedeNummer
    SET @HoogsteNummer = 'Nummers zijn gelijk' 
    ELSE
    SET @HoogsteNummer = 'Er is iets fout gegaan'

    RETURN @HoogsteNummer
END

现在他们几乎像他们应该的那样工作。但有一件事情并不完全正确。当我在我的函数中插入一个值时,结果是一个具有相同答案的完整列表。就像10行只有3,它只有1行,数字3.我知道我可以使用DISTINCT,但我觉得这个函数有问题。我尝试使用CASE / WHEN,但这也不起作用..

2 个答案:

答案 0 :(得分:1)

CREATE FUNCTION fnSpecNivAantal
(
 @Niveau as char(1)
)
RETURNS INT  --<-- since you are returning count use INT variable not char
AS 
BEGIN

    DECLARE @Aantal AS int; 

    IF (@Niveau IN ('A' , 'B', 'C'))
     BEGIN
       SELECT @Aantal = COUNT(*) 
       FROM STUK WHERE niveaucode = @Niveau
     END

RETURN @Aantal

END

抱歉无法理解你的第二个功能。

答案 1 :(得分:0)

将这些函数更改为内联表值函数将提供一些性能优势。它们是考虑功能的一种不同的方式,但值得付出努力。您需要了解的一个习惯是定义变量和参数的大小和精度。不要懒惰,做数字之类的事情。你应该精确并定义大小。 SQL Server不会自动调整比例和精度以满足它找到的值。相反,它使用的默认大小可能适合您的数据,也可能不适合。

您的第一个功能可以很好地简化为此。

ALTER FUNCTION fnHoogsteNummer 
    (
        @EersteNummer as numeric, --need to define scale and precision
        @TweedeNummer as numeric --need to define scale and precision
    )
RETURNS TABLE AS RETURN

    SELECT CASE WHEN @Eerstenummer > @TweedeNummer THEN convert(varchar(25), @EersteNummer)
            WHEN @TweedeNummer > @EersteNummer THEN convert(varchar(25), @TweedeNummer)
            WHEN @TweedeNummer = @EersteNummer THEN 'Nummers zijn gelijk' 
            ELSE 'Er is iets fout gegaan'
            END

第二个有点不同。您将函数定义为返回数字(无缩放或精度),但您的代码可以返回数字或字符串文字。这不起作用,因为函数的所有部分必须返回相同的数据类型。没有什么大不了的,你只需要意识到你的返回数据类型是varchar而不是数字。可以将此函数转换为内联表值函数,如下所示。

{{1}}

请注意,这两个功能都是一个声明。这就是使它们成为内联表值函数的原因。如果你开始定义变量并且有多个语句,它就会成为一个多语句表值函数,性能可能比标量函数更差。