首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用IF存在(选择.)在预插入触发器(Oracle)中

使用IF存在(选择.)在预插入触发器(Oracle)中
EN

Stack Overflow用户
提问于 2014-03-28 15:34:47
回答 1查看 55.2K关注 0票数 4

我的代码不起作用,Oracle告诉我触发器是在生成错误的情况下创建的。显然我无法得到更精确的关于构建错误的信息.

我以前真的没有做过很多SQL,所以我对语法不太熟悉。我有预感这是我的如果存在(选择.)然后说甲骨文不喜欢,我一直在谷歌寻找类似的例子,但我没有找到任何在我的情况下有效的东西。

关于密码:

  • “首次”是一个日期属性(它意味着开始)
  • "fin“是另一个日期属性(它意味着结束)
  • 如果这2行具有相同的"numInfirmier“属性,我希望确保新行的日期不会与表中的任何其他行重叠。
  • 因此,我选择了与新行和重叠日期具有相同numInfirmier的所有行。
  • 如果该选择中存在任何内容,我将引发一个错误。 如果存在监视,则在插入或更新监视之前创建或替换触发器chev_surv (从surveillance.numInfirmier = :NEW.numInfirmier和( surveillance.debut > :NEW.debut和surveillance.debut< :NEW.fin)或(surveillance.fin > :NEW.debut和surveillance.fin <:NEW.fin)的监视开始选择*)然后RAISE_APPLICATION_ERROR(-2001,‘;结束如果;结束;/

你知道怎么回事吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-28 15:51:23

首先,如果您使用的是SQL*Plus,当您创建一个对象并被告知存在编译错误时,show errors命令将显示这些错误。

如果运行show errors,就会被告知IF EXISTS不是有效的语法。你可以做这样的事

代码语言:javascript
复制
SELECT COUNT(*)
  INTO l_cnt
  FROM <<rest of query>>

IF( l_cnt > 0 )
THEN
  RAISE_APPLICATION_ERROR ...
END IF;

但是,一旦修复了编译错误,就会出现运行时错误。在surveillance上的行级触发器中,通常不能查询surveillance (如果您所做的只是保证只插入一行的INSERT VALUES )。如果这样做,您将在运行时得到一个可变的触发错误。

从数据模型的角度来看,当您发现自己设计了一个表,其中特定行的有效数据依赖于存储在同一表的其他行中的数据时,您通常违反了规范化原则,并且通常可以更好地修复底层数据模型。

如果您真的决定保留数据模型,我更愿意创建一个物化视图,该视图只为违反您的条件的行创建刷新提交的数据。然后,可以对该物化视图施加约束,在违反标准时在提交时抛出错误。这将需要表上的物化视图日志。

如果您确实希望保留数据模型,并且希望使用触发器来执行逻辑,则需要经典的三种触发器解决方案(如果使用11.2或更高版本,则需要由三部分组成的复合触发器)。您可以创建一个包含主键值集合的包。前置语句触发器将初始化集合。行级触发器将插入插入和/或更新到此集合中的行的主键。然后,after语句触发器将迭代这个集合,并实现任何您想要的检查。这是很多移动的碎片,这也是为什么我通常反对它。

此外,即使你让所有这些部分工作,你的逻辑不会保护你在一个多用户的环境。当多个用户同时访问系统时,完全有可能一个用户将插入一行,第二个用户将插入另一个具有重叠范围的行,然后每个会话都将提交。在这种情况下,这两组触发器都将允许更改,但仍然会在表中留下违反您的需求的数据。物化视图将在多用户环境中正常工作,因为它是在提交时而不是在插入时强制执行的。如果希望触发器在多用户环境中工作,则必须添加其他逻辑,以强制序列化,从而阻止第二个会话的insert在第一个会话提交或回滚之前运行。这增加了复杂性,降低了可伸缩性,并取决于实现方式,可能会造成支持噩梦。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22717136

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档