可以使用SQL约束来防止条件成立时更改特定值吗?

时间:2011-07-07 20:06:08

标签: sql constraints check-constraints

我知道SQL约束可以强制数据满足有效性标准。但是,诸如“学生成绩只能在'最终'标志为假”时才能更新标准呢?这样的更新标准是否必须由应用程序处理?

3 个答案:

答案 0 :(得分:4)

触发器,约束和附加列。

从结尾开始:

  1. 附加列存储要“固定”的值:

    ALTER TABLE ADD SavedGrade int
    
  2. 约束限制Grade列的更改:

    ALTER TABLE Students
    ADD CONSTRAINT CK_Grade CHECK (Finalised = 'false' OR Grade = SavedGrade)
    
  3. Grade列更新时,触发器会更新附加列(以下内容适用于SQL Server):

    CREATE TRIGGER StudentsFinaliseGrade
    ON Students AFTER INSERT, UPDATE
    AS
    IF UPDATE(Grade)
      UPDATE Students
      SET SavedGrade = i.Grade
      FROM inserted i
      WHERE i.ID = Students.ID
        AND i.Grade <> i.SavedGrade
    
  4. 因此,只要Finalised = 'false',就可以更改Grade列。当 更改时,该值会立即存储到SavedGrade列中。 (我们正在直接更新SavedGrade,否则约束不允许我们将Finalised设置为'true'。)一旦设置Finalised,您就不能再因约束而更改Grade列。

答案 1 :(得分:4)

简短回答:不,SQL限制本身不能阻止在Finalized为'true'时更改列等级(但允许更改)。

several kinds of SQL constraints:CHECK,DEFAULT,NOT NULL,UNIQUE,Primary Key和Foreign Key。

这些中的每一个都可以单独或组合地限制或影响列的值,但不能阻止UPDATE到允许的值。特别是,这些约束都不能阻止UPDATE根据之前的Grade和Finalized值进行评分和/或最终确定。

UPDATE触发器可以执行此操作:比较Grade的新旧值,如果这些值不同并且Finalized ='true',则使用解释性错误消息回滚UPDATE。

然而,应用程序可以而且应该更优雅地执行这样的“业务规则”。规则本身可以使用一些关于何时可以更改Finalized值的澄清。例如,是否允许更改等级并同时设置Finalized ='false'?触发器逻辑可以处理这些细节,将它安装为故障保护是合理的,同时使规则在应用程序的某处显示(前端/中间件/后端)。

答案 2 :(得分:-2)

IMO,我会说它应该在应用程序或存储过程(可能是两者)中完成,而不是作为一个实际约束(除了其他事项,在你的具体例子中,一个等级被“最终确定”没有'总是意味着它实际上是最终的。

但是,如果我将其作为约束实现,我将使用CHECK约束(再次使用您的示例)

CONSTRAINT chk_grade CHECK(grade between 0 AND 100 and finalized = 0)

检查具体语法,但这是我开始的地方。