UDF показывает странное поведение при проверке, содержит ли переменная нулевое значение - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь написать UDF, который используется проверочным ограничением, но, похоже, продолжает сталкиваться с проблемой.

При наличии полной пустой таблицы следующие результаты дают 1

declare @a float = (SELECT max(amount) FROM Bid WHERE auctionId = 1)
if(@a is null) select 1
else select 0

Но когда я пытаюсь внедрить подобную логику в UDF, он, похоже, возвращает 0 каждый раз, когда запускает ее для пустой таблицы.

CREATE FUNCTION dbo.fn_ck_newBidIsHigher(@auction int, @bid numeric(8,2))
RETURNS bit
BEGIN
    DECLARE @currentHighestBid float = (SELECT max(amount) FROM Bid WHERE auctionId = @auction)

    IF((@bid > @currentHighestBid) OR (@currentHighestBid is null))
    BEGIN
        RETURN 1
    END

    RETURN 0
END
GO

Я смотрю на это уже больше часа (может быть, в этом проблема), но я не могу понять, в чем дело.

Я вызываю функцию в проверочном ограничении следующим образом:

ALTER TABLE Bid ADD CONSTRAINT ck_New_Bid_Must_Be_Higher_Than_Previous_Bid CHECK(dbo.fn_ck_newBidIsHigher(auctionId, amount) = 1)

1 Ответ

0 голосов
/ 01 мая 2018

Вместо использования IF, как насчет использования CASE? При использовании CASE вы можете получить более 2 возможных результатов. F.E. 1 или 0 или NULL вместо 1 или 0.

Также безопаснее сравнивать значения одного типа.
Просто чтобы избежать каких-либо неожиданных побочных эффектов от неявного преобразования / преобразования перед сравнением.

CREATE FUNCTION dbo.fn_ck_newBidIsHigher(@auction int, @bid numeric(8,2))
RETURNS bit
BEGIN

    DECLARE @currentHighestBid numeric(8,2) = (SELECT max(amount) FROM Bid WHERE auctionId = @auction);

    DECLARE @result bit = (
      case 
      when @bid > @currentHighestBid then 1 
      when @bid <= @currentHighestBid then 0 
      end);

RETURN @result;
END
...