我有两张表如下:
department(alpha, college, etc.)
course(id, alpha, college, title, etc.)
大学和阿尔法在设计中都存在于两个表格中。我决定退化一点,因为在观看课程时总是需要大学和阿尔法。
我有一个触发器在department
表更新后执行,以便使用新的course
和alpha
值更新college
表中的所有行。我还有一个在更新course
表之前执行的触发器,以确保用户在其编辑中提交的alpha
- college
对存在于department
中表;如果该对不存在则会引发应用程序错误。
这些触发器发生冲突。第二个检查department
表的新值是否在它们中,但它们还没有,所以它会失败。
如果先执行第一个触发,是否可以忽略第二个触发?在这种情况下我真的不想执行第二个触发器,因为我知道值在第一个表中。如果那是不可能的,有没有更好的方法来做到这一点而不改变我的架构?
答案 0 :(得分:3)
你的第二个触发器听起来只不过是一个外键。删除它并在course
上创建外键约束。这在我的测试中有效。
然而,支持非规范化似乎不必要的工作,它几乎没有带来任何好处。如果您只想编写简单查询,请创建一个连接两个表并在查询中使用它的视图。如果你担心连接性能,我非常怀疑它会成为一个问题,除非你在表格上缺少明显的索引。
答案 1 :(得分:2)
我真诚地建议一起删除你的触发器方法,因为它有脏读的负担。每当我遇到这样的挑战时,我都会使用存储过程来实现DML。如果实施得当,你可以获得触发器的所有优点而不会头痛。
如果您担心自己想要确保部门表的所有更新都遵循您的逻辑,那么在课程中进行更改,请删除除存储过程所有者之外的任何用户的更新权限。这确保了唯一可以修改该表的调用者是您控制和理解的存储过程。巧合的是,它成为更新表格的唯一方法。
仅需0.02美元
答案 2 :(得分:2)
与使用触发器实现的大多数其他案例一样,您可以在此处看到负担,因为数据模型本身存在缺陷。
您可以实现与下面相同的逻辑,并使用PK和FK约束维护所有规则。
---Department references College...
Create table department(
department_id number primary key,
aplha varchar2(20) not null,
college varchar2(20) not null
);
***--Course belongs to a department.. so should be a child of department.
--If it's possible for different depts to give the same course (IT and CS),
--you'll have
--a dept_course_asc table***
Create table Course(
course_id number primary key
department_id number references department(department_id),
course_name varchar2(100) not null
);
如果您有学生表,则会将其与课程表与另一个student_table关联表关联。
可能看起来这些表格比您最初显示的表格多得多,但是如果您想避免数据冗余并且不希望在父表格中更改所有表格时更新列的负担,则上述模特是唯一的出路。
答案 3 :(得分:0)
这个问题有两种可能的解决方案。
解决方案1:使用DEFERRABLE FK约束。
只有当(alpha,college)组合是唯一的且可以定义为部门表的PK时,才能使用此解决方案。 在这种情况下,您不需要课程表上的触发器。
相反,您可以在引用部门表的课程中定义DEFERRABLE FK(alpha,college)。
在部门更新之前,您必须执行SET CONSTRAINT ... DEFERRED语句see documentation。 然后在提交之前不会验证FK。
解决方案2:使用系统上下文
使用本地system_context关闭第二个触发器。
必须首先创建上下文。 see User Created Contexts
部门的触发器在上下文中将变量设置为某个值。
在课程的第二个触发器中,您可以检查上下文中变量的值