Ограничение CHECK не возвращает то же самое, что вызываемые функции - PullRequest
0 голосов
/ 20 мая 2019

Я настраиваю веб-сайт аукциона для школьного проекта, и мне нужно установить ограничение 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

В таблице Item есть тестовый элемент с этими (соответствующими) столбцами:

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».

Таблица Bid имеет следующие столбцы: - Item, который является ссылкой FK на таблицу Item.- BidValue, значение ставки.- Пользователь, пользователь, который сделал ставку.- BidDay, день, в который была сделана заявка.- BidTime, отметка времени.

1 Ответ

0 голосов
/ 20 мая 2019

Кажется, что использование пользовательских функций в пределах ограничений 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...