代码之家  ›  专栏  ›  技术社区  ›  Am1rr3zA

触发器、断言和检查(在数据库中)之间的区别是什么?

  •  22
  • Am1rr3zA  · 技术社区  · 15 年前

    有人能解释(或建议一个网站或论文)触发器、断言和检查之间的确切区别吗?也能描述我应该在哪里使用它们?

    编辑:我的意思是在数据库中,而不是在任何其他系统或编程语言中。

    5 回复  |  直到 8 年前
        1
  •  54
  •   jellomonkey    15 年前

    触发器 -触发器是在数据库中的更新、插入或删除之前或之后执行的一段SQL。用纯英语编写的触发器示例可能类似于:在更新客户记录之前,请保存当前记录的副本。看起来像是:

    CREATE TRIGGER triggerName
    AFTER UPDATE
        INSERT INTO CustomerLog (blah, blah, blah)
        SELECT blah, blah, blah FROM deleted
    

    断言和检查之间的区别更加模糊,许多数据库甚至不支持断言。

    检查约束 -检查是SQL的一部分,它确保在对记录执行操作之前满足条件。用简单的英语来说,这是这样的:所有客户的账户余额必须至少为100美元。看起来像是:

    ALTER TABLE accounts 
    ADD CONSTRAINT CK_minimumBalance
    CHECK (balance >= 100)
    

    任何尝试在余额列中插入小于100的值都会引发错误。

    断言 -断言是确保满足条件或停止对 数据库对象 . 这可能意味着锁定整个表,甚至整个数据库。

    为了使事情更混乱-可以使用触发器强制检查约束,并且在某些DBS中可以代替断言(通过允许您运行与被修改的表无关的代码)。初学者常见的错误是在需要触发器时使用检查约束,或者在需要检查约束时使用触发器。

    例如:所有新开户的客户必须有100美元的余额;但是,一旦开户,他们的余额可能会低于该金额。在这种情况下,必须使用触发器,因为您只希望在插入新记录时评估条件。

        2
  •  11
  •   Erwin Smout    13 年前

    在SQL标准中,断言和检查约束都是关系理论所称的“约束”:数据库中实际包含的数据必须遵守的规则。

    两者之间的区别在于,在某种意义上,检查约束要简单得多:它们是只与一行相关的规则,而断言可以涉及任何数量的其他表或同一表中的任何数量的其他行。很明显,这很重要。对于DBMS构建者来说,支持它更为复杂,这反过来也是他们不支持它的原因:他们只是不知道怎么做。

    触发器是一段可执行代码,可以向DBMS声明,每次对某个表执行某种更新操作(insert/delete/update)时都应执行这些代码。因为触发器可以引发异常,所以它们是实现与断言相同事物的一种方法。然而,对于触发器,仍然是程序员必须进行所有的编码,并且不会犯任何错误。

    编辑

    有一天,什么时候的评论。断言/检查CNSTR。是正确的。不同之处是更加微妙(和混乱)。该标准确实允许在检查约束中使用子查询。(大多数产品都不支持它,所以我的“与单行相关”对于大多数SQL产品都是正确的,但对于标准产品则不是如此。)那么还有区别吗?是的,还有。不止一个偶数。

    第一种情况:表男(id:integer)和表女(id:integer)。现在想象一下这样一个规则:“没有身份证值可以同时出现在男性和女性的桌子上”。这是一条规则。断言的目的正是数据库设计者将声明这个单一的规则[并用它来完成],DBMS将知道如何[有效地,当然]处理这个规则,以及如何执行这个规则,不管对数据库做了什么特定的更新。在本例中,DBMS知道必须在插入到男性和插入到女性时检查此规则,但在从男性/女性中删除或插入到<anyothertable>时不检查此规则。

    但是DBMS不够聪明。那么需要做什么呢?数据库设计器必须向其数据库添加两个检查约束,一个约束到男子表(根据女子表检查新插入的男子ID),另一个约束到女子表(反过来检查)。你的第一个区别是:一条规则,一个主张, 检查约束。与断言相比,检查约束是一个较低的抽象级别,因为它们要求设计人员更多地考虑自己:(a)可能导致其断言被违反的所有类型的更新,以及(b)对于他在(a)中发现的任何特定“更新类型”应执行什么特定检查。(虽然我不喜欢对什么仍然是“什么”和什么是“如何”做“绝对”的陈述,但我总结说,检查约束需要数据库设计器进行更多的“如何”思考(过程性),而断言允许数据库设计器只关注“什么”(声明性)。

    第二种情况(尽管我不完全确定这一点——所以吃一粒盐):只是你的平均RI规则。当然,您可以使用一些引用子句来指定这一点。但假设引用子句不可用。像“每个订单都必须由已知客户下”这样的规则实际上就是一个规则,因此:一个断言。然而,我们都知道这样的规则总是可以通过两种方式被违反:插入订单(在本例中)和删除客户。现在,根据前面的男人/女人的例子,如果我们想使用检查约束来实现这个单一的规则/断言,那么我们就必须编写一个检查约束,在插入到订单中时检查客户的存在,但是我们可以编写什么检查约束来执行任何需要的操作 删除 来自客户?据我所知,它们根本不是为这个目的而设计的。第二个区别是:检查约束以独占方式绑定到插入,断言可以定义在删除时也将检查的规则。

    第三种情况:想象一个表组合(componentid:)。百分比:整数),以及“所有百分比的总和必须始终等于100”的规则。这是一条规则,断言可以指定它。但是试着想象一下,你将如何使用检查约束来执行这样一个规则……如果您有一个有效的表,例如,三个非零行加起来是100行,那么您将如何对该表应用任何可以在检查约束之后继续存在的更改?您不能删除或更新(减少)任何行,而不必添加其他替换行,或更新总计为相同百分比的其余行。同样,对于插入或更新(增加)。您至少需要延迟约束检查,然后您要检查什么?第三个区别是:检查约束针对单个行,断言还可以定义/表示“跨越”多行的规则(即关于行聚合的规则)。

        3
  •  5
  •   Mohamed Adel    8 年前

    断言不会修改数据,它们只检查某些条件

    触发器更强大,因为它可以检查条件并修改数据

    ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————

    断言不链接到数据库中的特定表,也不链接到特定事件

    触发器链接到特定表和特定事件

        4
  •  1
  •   marc_s    8 年前

    数据库约束涉及更新数据库时必须满足的条件。在SQL中,如果约束条件的计算结果为false,则更新失败,数据保持不变,DBMS生成错误。

    两个 CHECK ASSERTION 是由SQL标准定义的数据库约束。一个重要的区别是 检查 应用于特定的基表,而 断言 应用于整个数据库。考虑限制表中组合行的约束 T1 T2 总共10行,例如

    CHECK (10 >= (
                  SELECT COUNT(*)
                    FROM (
                          SELECT *
                            FROM T1
                          UNION
                          SELECT * 
                            FROM T2
                         ) AS Tn
                 ))
    

    假设表是空的。如果这是作为 断言 只有一个用户试图将11行插入 T1 然后更新就会失败。如果将约束作为 检查 约束 T1级 只有。但是,如果约束作为 检查 约束 T2 只有约束才能成功,因为语句的目标是 T1 不会导致应用于 T1 进行测试。

    两个 断言 和A 检查 可以延期(如果声明为 DEFERRABLE ,允许数据临时违反约束条件,但仅限于事务内。

    断言 检查 涉及子查询的约束是核心标准SQL之外的特性,并且没有一个主要的SQL产品支持这些特性。MS Access(不完全是工业级产品)支持 检查 涉及子查询但不可延迟的约束加上约束测试的约束总是逐行执行,实际结果是功能非常有限。

    常见于 检查 约束,触发器将应用于特定表。因此,触发器可用于实现与 检查 约束,但不是 断言 . 触发器是过程代码,与约束不同,用户必须对性能和错误处理等问题承担更大的责任。大多数商业SQL产品都支持触发器(前面提到的MS访问不支持)。

        5
  •  0
  •   Feri    11 年前

    对于要触发的触发器,表达式应为true,但如果表达式为false,则将计算check。