首先,如果您正在使用SQL * Plus,当您创建一个对象并被告知存在编译错误时,命令show errors将显示错误.
如果你运行show errors,你会被告知IF EXISTS是无效的语法.你可以做点什么
SELECT COUNT(*)
INTO l_cnt
FROM <>
IF( l_cnt > 0 )
THEN
RAISE_APPLICATION_ERROR ...
END IF;
但是,一旦修复了编译错误,就会出现运行时错误.在监视的行级触发器中,您通常不能查询监视(如果您正在执行的是INSERT VALUES,则可以保证仅插入单行).如果这样做,您将在运行时遇到变异触发错误.
从数据模型的角度来看,当您发现自己设计一个表,其中特定行的有效数据取决于存储在同一个表的其他行中的数据时,您通常违反了规范化原则,并且通常更好地修复了基础数据模型.
如果你真的决定保留数据模型,我宁愿创建一个在提交时刷新的物化视图,它只包含违反你标准的行的数据.然后,您可以在物化视图上设置约束,在违反条件时在提交时抛出错误.这将需要您桌面上的物化视图日志.
如果您真的想要保留数据模型并且想要使用触发器强制执行逻辑,那么您需要经典的三触发解决方案(如果您使用11.2或更高版本,则需要具有三个部分的复合触发器).您将创建一个包含主键值集合的包. before语句触发器将初始化集合.行级触发器将插入已插入和/或更新到此集合中的行的主键.然后一个after语句触发器将遍历此集合并实现您想要的任何检查.然而,这是很多动人的作品,这就是为什么我通常会反对它.
此外,即使您将所有这些部分都工作,您的逻辑也无法在多用户环境中保护您.当您有多个用户同时访问系统时,一个用户完全可能插入一行,第二个用户将插入另一个具有重叠范围的行,然后每个会话都将提交.在这种情况下,两组触发器都允许更改,但您仍然会在表格中留下违反要求的数据.物化视图,因为它在提交时而不是在插入时强制执行,将在多用户环境中正常工作.如果您希望触发器在多用户环境中工作,则必须通过添加其他逻辑来进一步使它们复杂化,这些逻辑强制执行序列化,阻止第二个会话的插入运行,直到第一个会话提交或回滚.这增加了复杂性,降低了可扩展性,并且取决于它的实现方式,可能会导致支持噩梦.