检查列值是否高于具有相应列的其他行

Check if column value is higher than other rows with corresponding columns

在 SQL 服务器中,我在检查约束中的多行时遇到问题。

对于出价系统,table 包含以下列:

ObjectID [INT] 
BidAmount [NUMERIC(9,2)] 
User [VARCHAR(40)] 
Date [DATETIME] 

我想确保插入的出价 BidAmount 高于此 ObjectID 的其他出价。

我尝试在检查约束中使用用户定义的函数来执行此操作,但事实证明这非常不可靠(有时允许插入,有时被拒绝。似乎没有模式).

出价table:

CREATE TABLE Bid 
(
    ObjectID INT NOT NULL,
    BidAmount NUMERIC(9,2) NOT NULL,
    User VARCHAR(40) NOT NULL,
    Date DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,

    CONSTRAINT PK_Bod 
        PRIMARY KEY (ObjectID, BidAmount),
    CONSTRAINT FK_Bod_User 
        FOREIGN KEY (User) REFERENCES User (Username),
    CONSTRAINT FK_Bod_Object 
        FOREIGN KEY (ObjectID) REFERENCES Object (ObjectID),
    CONSTRAINT AK_Bod_Gebruikersmoment UNIQUE (User, Date),
    CONSTRAINT AK_Bod_Voorwerpmoment UNIQUE (ObjectID, Date),
    CONSTRAINT CK_Bodhoogte 
        CHECK (BidAmount > dbo.krijgMinimaleBod(ObjectID, Date))
)

我尝试使用的用户自定义函数:

CREATE FUNCTION dbo.krijgMinimaleBod (@ObjectID INT)
RETURNS NUMERIC(9,2)
AS
BEGIN
    DECLARE @highestBid NUMERIC(9,2)

    SELECT @highestBid = ISNULL(MAX(BidAmount), V.StartPrice)
    FROM Object V
    LEFT JOIN Bid B ON B.ObjectID = V.ObjectID
    WHERE V.ObjectID = @ObjectID
    GROUP BY V.ObjectID, V.StartPrice;

    RETURN @highestBid
END

我该如何防止系统插入的行中 BidAmount 低于同一产品的其他数量?

CHECK Constraints 非常适合在单行上进行检查。尝试访问目标 table 或其他目标上的其他行时,事情会变得复杂。

我强烈认为执行此逻辑并不是 table 的真正责任。出价是什么。您可以让出价 A=10$,随后的出价 B=20$,但随后检测到错误,您实际上必须将出价 A 更新为 30$。那应该怎么办?可能什么都没有;另一种方法是扩展您的问题以包括更新,从而导致更复杂的情况。

相反,运行 INSERTs 的用户有责任正确执行此操作。更有条理的方法是使用过程从 user/application 执行插入。此过程可以在插入之前进行检查,并且 throw 无需使用触发器。

我在 T-SQL 中使用触发器解决了这个问题。

CREATE TRIGGER Bid_HighEnough ON dbo.Bod
AFTER INSERT, UPDATE
AS
    IF EXISTS (SELECT 'Wrong'
                FROM Inserted I INNER JOIN Bid B
                ON I.ObjectID = B.ObjectID
                INNER JOIN Object V
                ON I.ObjectID = V.ObjectID
                WHERE I.BidAmount < V.StartPrice OR I.BidAmount < B.BidAmount
    BEGIN
        THROW 50000, 'No bids allowed lower than previous bids.', 1
    END

感谢您的评论。