在插入数据行时创建触发器并检查具有给定范围内值的特定列

Create a trigger when Inserting Data Row and check specific Column that have values in given range

触发器不工作。我只想不允许输入不在数据库范围内的标记。

这是我试过的代码。

table

CREATE Table Marks
(
    TestID VARCHAR(10),
    StudentID VARCHAR(10),
    Grade CHAR(1),
    Marks FLOAT,
    IssuedDate VARCHAR(10),

    PRIMARY KEY (TestID, StudentID),
    CONSTRAINT FK66 
        FOREIGN KEY(TestID) REFERENCES Test(TestID),
    CONSTRAINT FK77 
        FOREIGN KEY(StudentID) REFERENCES Student(StudentID)
)

触发器:

CREATE TRIGGER checkRange
ON Marks
FOR INSERT
AS
BEGIN
    DECLARE @marks FLOAT
    DECLARE @tID VARCHAR(10)
    DECLARE @stID VARCHAR(10)

    SELECT @marks = Marks, @tID = TestID, @stID = StudentID
    FROM inserted

    IF (((@marks) < 0) AND ((@marks) > 100))
        ROLLBACK TRANSACTION

    DELETE FROM Marks 
    WHERE TestID = @tID AND StudentID = @stID
END

正在插入数据:

INSERT INTO Marks 
VALUES ('T02','ST00000001','F',110,'2019-08-24')
IF((@marks > 100.00) OR (@marks < 0.00))

到目前为止,更好的答案是 check constraint。但我会把我的留在这里,以便您更好地理解触发器。

您实际要寻找的是类似以下内容的内容,它处理 Inserted 可以有 0-N 行的事实(当 Inserted 包含除 1 以外的任何内容时,您当前的解决方案将中断行)。

鉴于您已经发出了 ROLLBACK,可能没有理由 DELETE 任何东西,除非您想删除在当前 INSERT 语句之前添加的行。

CREATE TRIGGER checkRange
ON Marks
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS (
        SELECT 1
        FROM Inserted I
        WHERE Marks > 100.00 OR Marks < 0.00
    ) BEGIN
        --ROLLBACK TRANSACTION;
        -- Don't rollback in a trigger, throw instead. "A rollback causes a weird error The transaction ended in the trigger. The batch has been aborted" (thanks Charlieface).
        THROW 51000, 'Marks are out of range, either > 100 or < 0.', 1; 
    END;
END;

我认为的注释:

  • varchar(10)是PK的糟糕选择,为什么不用int identity
  • float 对 Marks 来说是一个糟糕的选择,除非你正在存储科学信息,否则你不应该使用 float 因为它不存储精确的数字。你想要一个 decimal(9,2) 或类似的东西。
  • varchar(10) 是一个糟糕的日期选择,请使用 date 日期类型,否则您将在余生中遇到此问题。

正如其他人所提到的,您的触发器存在一些严重问题。

看来您需要 Marks 列在每个学生的每个测试中在 0-100 之间,如果这样,更好的解决方案是检查约束:

ALTER TABLE Marks
    ADD CONSTRAINT CHK_Marks
        CHECK (Marks >= 0 AND Marks <= 100);