当前位置: 首页 > 面试题库 >

数据库触发器对跨表完整性约束是否安全?

袁帅
2023-03-14
问题内容

我建议使用触发器来检查跨表完整性约束,以回答此问题。在评论中建议它可能会引起问题:

进行跨行检查的触发器在大多数数据库上很少起作用…因为它们无法从其他事务中读取未提交的行

不过,我没有找到任何支持该说法的消息来源。官方
文档未提及任何内容。我发现的其他问题在本文的SO上进行了介绍它主要批评潜在的隐藏复杂性,因为一眼就看不到触发器。但是,即使是评分最高的答案也承认其用于完整性问题。

所以我的问题是: 数据库触发器对跨表完整性约束是否安全 具体来说,以下解决方案行得通吗?

总结一下原来的问题。我们有桌子

  • Player - PlayerID, PlayerName
  • Bet - BetID, BetName
  • plays_in - BetID, PlayerID

约束条件是BetName和PlayerID的组合应该唯一。建议触发器的定义:

CREATE TRIGGER check_bet_name BEFORE INSERT ON plays_in 
  FOR EACH ROW BEGIN
      DECLARE bet_exists INT DEFAULT 0;
      DECLARE msg VARCHAR(255);

      SELECT 1 INTO bet_exists 
        FROM Bet AS b1
        WHERE b1.BetID = NEW.BetID
          AND EXISTS (SELECT * 
            FROM plays_in AS p JOIN Bet AS b2 USING (BetID)
            WHERE p.PlayerID = NEW.PlayerID AND b2.BetName = b1.BetName
          )
        LIMIT 1;

      IF bet_exists THEN
        SET msg = "Bet name already exists...";
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
      END IF;
  END//

问题答案:

答案是 触发器不安全

事实证明,触发器确实看不到其他事务中未提交的更改,并且没有错误地通过。这样可以证明

交易1:

START TRANSACTION;
INSERT INTO plays_in (BetID, PlayerID) VALUES (1,1); -- query A

交易2:

START TRANSACTION;
INSERT INTO plays_in (BetID, PlayerID) VALUES (1,2); -- query B; in conflict with A, but passses

两项交易:

COMMIT;

plays_in即使A和B在单个事务中执行,现在也会包含两个插入的记录,触发器将引发错误。

整个示例资源可以在这里找到



 类似资料:
  • 主要内容:1. 域限制,2. 实体完整性约束,3. 参照完整性约束,4. 键限制(约束)完整性约束是一组规则,它用于保持信息质量。 完整性约束确保必须以不影响数据完整性的方式执行数据插入,更新和其他过程。 因此,完整性约束用于防止对数据库的意外损坏。 完整性约束的类型 1. 域限制 域约束可以定义为属性的有效值集的定义。 域的数据类型包括字符串,字符,整数,时间,日期,货币等。属性的值必须在相应的域中可用。 示例 - 2. 实体完整性约束 实体完整性约束表明主键值不能为空()。 这是

  • 本文向大家介绍数据库设计的完整性约束表现在哪些方面,包括了数据库设计的完整性约束表现在哪些方面的使用技巧和注意事项,需要的朋友参考一下 数据库设计的完整性约束表现哪些方面?主要就是下面写四个方面: 1、域的完整性:数据库表中的列必须满足某种特定的数据类型或约束。其中约束又包括取值范围、精度等规定。用Check来实现约束,在数据库设计工具中,对字段的取值范围进行定义时,有一个Check按钮,通过它定

  • 无法删除或更新父行:外键约束失败(.,constraint外键()引用()) 文件实体代码: 扩展实体代码:

  • 问题内容: 是否可以将触发器应用于MySQL中的跨数据库访问?如果是,请举一个例子。我的目的是如果在database1中插入/更新/删除了任何新数据,则在database2中插入/更新/删除数据。我正在使用MySQL 5.1 问题答案: 是的你可以。您可以创建一个过程并在触发器中调用它。程序示例: 然后创建触发器:

  • 问题内容: 在多个数据库之间保持引用完整性的最佳实践是什么?因为没有内置功能 还是对单个数据库进行分区更好? 更新 请参见下面的kevin的示例。那是我的情况。我的库存数据库具有引用雇员数据库中的employeeId的表。 这些数据库当前维护在不同的位置(不同的服务器) 问题答案: 使用2k05 / 2k08,最好对单个数据库进行分区。您拥有将数据存储在多个数据库中的所有好处,同时能够使用单个数据

  • 本文向大家介绍如何在Oracle中使用主键约束和外键约束来增强数据库完整性?,包括了如何在Oracle中使用主键约束和外键约束来增强数据库完整性?的使用技巧和注意事项,需要的朋友参考一下 问题: 您要使用主键约束和外键约束来强制Oracle中的数据库完整性。 解 在以完整性定义的表上执行的任何DML语句(INSERT,UPDATE或DELETE)都有助于确保表中的行保持其完整性。 让我们看一些显示