CHECK约束返回的结果与调用的函数不同

时间:2019-05-20 08:13:19

标签: sql-server tsql

我正在为一个学校项目建立一个拍卖网站,并且我必须进行CHECK约束,以检查出价是否有效。 CHECK约束调用三个函数: -fn_getHighestBid返回此项目的最高出价。 -fn_getMinimumRaise返回当前最高出价和插入的出价之间的最小值。 -fn_isValidBid检查以上两个功能,并返回是否可以插入出价。

当我使用SELECT获取功能的结果时,它们将返回预期的结果。但是当我尝试向表中插入内容时,它违反了CHECK约束。

我尝试将WITH CHECK添加到向数据库添加了约束的查询,但是没有任何改变。

CREATE FUNCTION dbo.fn_getHighestBid (@Item BIGINT)
RETURNS NUMERIC(10, 2)
AS
BEGIN
    DECLARE @highestBid NUMERIC(10, 2) = 0
    IF (SELECT COUNT(*) FROM Bid WHERE Item = @Item) = 0 -- Checks whether there are any bids for this auctioned item.
    SET @highestBid = (SELECT Startingprice FROM Item WHERE ItemID = @Item)
    ELSE SET @highestBid = (SELECT MAX(BidValue) FROM Bid WHERE Item = @Item)

    RETURN @highestBid
END
GO

CREATE FUNCTION dbo.fn_getMinimumRaise (@Item BIGINT)
RETURNS NUMERIC(10, 2)
AS
BEGIN
    DECLARE @minimumRaise NUMERIC(10, 2) = 0
    DECLARE @highestBid NUMERIC(10, 2) = dbo.fn_getHighestBid(@Item)


    SET @minimumRaise = CASE
    WHEN @highestBid BETWEEN 1.00 AND 49.99 THEN 0.50
    WHEN @highestBid BETWEEN 49.99 AND 499.99 THEN 1.00
    WHEN @highestBid BETWEEN 500.00 AND 999.99 THEN 5.00
    WHEN @highestBid BETWEEN 1000.00 AND 4999.99 THEN 10.00
    WHEN @highestBid >= 5000.00 THEN 50.00
    ELSE 0.00
    END

    RETURN @minimumRaise
END
GO

CREATE FUNCTION dbo.fn_isValidBid (@Item BIGINT, @BidValue NUMERIC(10, 2))
RETURNS BIT
AS
BEGIN
    DECLARE @minimumRaise NUMERIC(10, 2) = dbo.fn_getMinimumRaise(@Item)
    DECLARE @highestBid NUMERIC(10, 2) = dbo.fn_getHighestBid(@Item)

    IF @BidValue >= (@highestBid + @minimumRaise) RETURN 1

    RETURN 0
END

约束如下:

ALTER TABLE Bid
ADD CONSTRAINT CHK_Bid_BidValue
CHECK (dbo.fn_isValidBid(Item, BidValue) = 1)
GO

“项目”表中有一个测试项目,其中包含以下(相关)列:

ItemID = 1 Startprice = 50.00

以下查询:

SELECT dbo.fn_getHighestBid(1), dbo.fn_getMinimumRaise(1), dbo.fn_isValidBid(1, 51.00)

它返回50.00、1.00和1(按预期)。 但是,当我尝试使用此INSERT插入出价时:

INSERT INTO Bid (Item, BidValue, User) VALUES (1, 51.00, 'TestUser2') -- TestUser2 is the user that places the bid.

它返回错误消息: INSERT语句与CHECK约束“ CHK_Bid_BidValue”冲突。在数据库“ testdatabase”的表“ dbo.Bid”中发生了冲突。

“出价”表包含以下列: -物料,这是对物料表的FK引用。 -BidValue,出价的值。 -用户,即出价的用户。 -BidDay,出价所在的日期。 -BidTime,时间戳。

1 个答案:

答案 0 :(得分:0)

似乎在CHECK约束中使用用户定义的函数是有问题的。例如,查看:

也许您可以用触发器替换CHECK约束。例如:

CREATE TRIGGER [TR_Bid_insert]
ON [dbo].[Bid]
INSTEAD OF INSERT
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS (SELECT * FROM INSERTED WHERE [dbo].[fn_isValidBid] ([Item], [BidValue]) = 0) BEGIN
        RAISERROR ('Attempting to insert invalid bid.', 16, 1);
        ROLLBACK TRANSACTION;
    END;
END;