Sql 插入数据行时创建触发器,并检查具有给定范围值的特定列
触发器不工作。我只想不允许输入不在数据库范围内的标记 这是我试过的代码 桌子Sql 插入数据行时创建触发器,并检查具有给定范围值的特定列,sql,sql-server,tsql,triggers,Sql,Sql Server,Tsql,Triggers,触发器不工作。我只想不允许输入不在数据库范围内的标记 这是我试过的代码 桌子 CREATE Table Marks ( TestID VARCHAR(10), StudentID VARCHAR(10), Grade CHAR(1), Marks FLOAT, IssuedDate VARCHAR(10), PRIMARY KEY (TestID, StudentID), CONSTRAINT FK66 FOREIGN
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
到目前为止,更好的答案是检查约束。但我会把我的留在这里,让你更好地理解 您实际要查找的是以下内容,它处理插入的行可以有0-N行的事实,当插入的行包含除1行以外的任何行时,当前解决方案将中断 如果已经发出回滚,则可能没有理由删除任何内容,除非要删除在当前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;
注意,我认为:
varchar10对于PK来说是个糟糕的选择,为什么不使用int标识呢?
对于标记来说,浮点是一个糟糕的选择,除非您存储的是科学信息,否则永远不要使用浮点,因为它不能存储精确的数字。你需要一个小数点9,2或类似的数字。
varchar10对于约会来说是一个糟糕的选择,请使用日期类型,否则您将在它的余生中遇到问题。
正如其他人提到的,你的触发器有很多严重的问题 似乎您需要每个学生每次测试的分数列在0-100之间,如果是这样,更好的解决方案是检查约束: 更改表格标记 添加约束CHK_标记
复选标记>=0,并且您正在使触发器101出错,插入的标记可以有0-N行,而不仅仅是1行。您必须像对待任何表一样对待它,并使用基于集合的操作,而不是过程逻辑。这部剧怎么演。触发器不起作用实际上意味着什么?我刚刚在这里发现了问题IF@marks100'当我更改时触发器正在工作'IF@marks>100.00'我想检查标记是否为0或大于100。但是如果插入两行,则不起作用。为什么在此处使用触发器?约束似乎是更好的解决方案。IssuedDate VARCHAR10,不,不。想想你的数据类型!这完全是错误的。varchar10对studentid来说不是一个糟糕的选择。假设它从不改变,它可能代表一个用户名。例如,它只有10个字节,如果根据ID查询其他表,那么它会保存一个joinNote。另外,按主键分组意味着您实际上没有分组,因此分组方式是浪费时间。^^ true dat,我没有仔细看桌子的设计。我不会使用用户名作为PK,这会造成各种其他复杂性,以确保用户名保持唯一性,并首先进行分配。
IF((@marks > 100.00) OR (@marks < 0.00))
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;