Oracle 数据库中的冲突触发器
我有两个表,如下所示:
department(alpha, College, etc.)
course(id, alpha, College, title, etc.)
College 和 alpha 都存在于两个表中设计的表格。我决定稍微去规范化,因为在观看课程时总是需要大学和阿尔法。
我有一个触发器,在更新 department
表后执行,以便它使用新的 alpha
和 更新
价值观。我还有一个在更新 course
表中的所有行>大学course
表之前执行的触发器,以确保用户在他或她的提交中提交的 alpha
-college
对department
表中存在编辑内容;如果该对不存在,则会引发应用程序错误。
这些都会引发冲突。第二个检查 department
表的新值是否在其中,但它们还没有,所以它会像应该的那样失败。
如果先执行第一个触发器,是否可以忽略第二个触发器?在这种情况下,我真的不想执行第二个触发器,因为我知道这些值位于第一个表中。如果这是不可能的,是否有更好的方法可以在不更改我的架构的情况下做到这一点?
I have two tables as follows:
department(alpha, college, etc.)
course(id, alpha, college, title, etc.)
College and alpha are present in both tables by design. I decided to de-normalize a little because the college and alpha are always desired when viewing a course.
I have one trigger that executes after the department
table is updated so that it updates all rows in the course
table with the new alpha
and college
values. I also have a trigger that executes before updating the course
table to make sure that the alpha
-college
pair that the user submitted in his or her edits exists in the department
table; if the pair isn't there it raises and application error.
These triggers conflict. The second one checks that the new values for the department
table are in their, but they aren't yet so it fails like it should.
Is it possible to ignore the second trigger if the first trigger is executed first? I really don't want to execute the second trigger in this case, since I know the values are in the first table. If that's not possible, is there a better way to do this without changing my schema?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你的第二个触发器听起来只不过是一个外键。删除它并在
course
上创建外键约束。这在我的测试中有效。然而,支持非规范化似乎是不必要的工作,几乎没有什么好处。如果您只想编写简单的查询,请创建一个连接两个表的视图并在查询中使用它。如果您担心连接性能,我非常怀疑这会是一个问题,除非您缺少表上明显的索引。
Your second trigger sounds like nothing more than a foreign key. Drop it and create a foreign key constraint on
course
instead. That works in my tests.However, it seems like unnecessary work to support a denormalization that provides little benefit. If you just want to write simple queries, create a view that joins the two tables and use that in your queries. If you are concerned about the join performance, I doubt very much that it will be a problem, unless you are missing obvious indexes on the tables.
我真诚地建议您一起删除您的触发方法,因为它受到脏读的负担。每当我遇到这样的挑战时,我都会仅使用存储过程来实现 DML。如果实施得当,您将获得触发器的所有优势,而不会感到头疼。
如果您担心要确保部门表的所有更新都遵循您的逻辑,就像课程中的更改一样,请删除除存储过程所有者之外的任何用户的更新权限。这确保了唯一可以修改该表的调用者是您控制和理解的存储过程。巧合的是,它成为更新表的唯一方法。
只需 0.02 美元
I would sincerely recommend removing your trigger approach all together since it's burdened by dirty reads. Whenever I faced a challenge such as this I would implement the DML using Stored Procedures only. You get all the advantages of triggers without the headaches if implemented properly.
If your fear is you want to make sure all updates to the department table follow your logic as do changes in course, remove update permissions to any user except the owner of the stored procedure. This ensures the only caller who can modify that table is the stored procedure you control and understand. And by coincidence, it becomes the only way to update the tables.
Just $0.02
与使用触发器实现的大多数其他情况一样,您可以看到这里的负担,因为数据模型本身存在缺陷。
您可以实现与下面相同的逻辑,并使用 PK 和 FK 约束维护所有规则。
如果您有学生表,则可以将其与课程表和另一个 Student_table 关联表关联起来。
这些表可能比您最初显示的要多得多,但如果您想避免数据冗余,并且不希望在父表中更改所有表中的列时承担更新列的负担,则上述模型是唯一的出路。
Like most other cases implemented with triggers, you can see the burden here because the data-model itself has defects.
You can implement the same logic as below and maintain all rules using PK and FK constraints.
if you have a student table, you'll associate it with the course table with another student_table association table.
It might appear these are a lot more tables than you intially showed, but if you want to avoid data redundancies and don't want to have the burden of updating columns in all tables whenever they change in the parent table, the above model is the only way to go.
该问题有两种可能的解决方案。
解决方案 1:使用 DEFERRABLE FK 约束。
仅当(alpha、college)组合唯一并且可以定义为部门表的 PK 时,此解决方案才可行。
在这种情况下,您不需要课程表上的触发器。
相反,您可以在引用部门表的课程上定义 DEFERRABLE FK(alpha、college)。
在部门更新之前,您必须执行 SET CONSTRAINT ... DEFERRED 语句 请参阅文档。
那么FK在提交之前不会被验证。
解决方案 2:使用系统上下文
您可以使用本地 system_context 关闭第二个触发器。
必须首先创建上下文。 查看用户创建的上下文
部门上的触发器将上下文中的变量设置为某个值。
在课程的第二个触发器中,您检查上下文中变量的值
There are two possible solutions to the problem.
Solution 1: Using DEFERRABLE FK constraint.
This solution is only possible if (alpha, college) combination is unique and can be defined as a PK for department table.
In this case, you do not need the trigger on the course table.
Instead, you define a DEFERRABLE FK (alpha, college) on course that referenced the department table.
And before the update on department you must execute SET CONSTRAINT ... DEFERRED statement see documentation.
Then the FK will be not verified until the commit.
Solution 2: Using system context
You switch off the second trigger using the local system_context.
The context must be created first. see User Created Contexts
The trigger on department set a variable in the context to a some value.
And in the second trigger on courses you check the value of the variable in the context