我已经分析了一个hibernate生成的oracle数据库,并发现从一个表中删除一行将产生1200+触发器的触发,以便删除子表中的相关行。触发器都是自动生成的 - 自动删除子行而不先检查是否存在。由于不可能预测哪些子表实际上会有相关的行,我认为一个可行的解决方案是防止级联删除在一个深度分支的完全空的肢体上发射,将是在尝试之前检查相关行的存在删除。在其他dbms'中,我可以在删除之前简单地说“if exists .....”。在oracle中有没有类似的方法可以做到这一点?
答案 0 :(得分:4)
“从单个表中删除一行将产生1200+触发器的触发” 这些语句或行级触发器是? 如果是后者,只有在删除行时才会触发。假设您在客户上有一个BEFORE DELETE触发器来删除客户订单,并且在订单上有一个BEFORE DELETE触发器来删除订单商品。如果客户没有订单,并且订单表触发器是行级触发器,则它不会从订单商品中触发删除。
“在尝试删除之前检查是否存在相关行” 可能没什么好处。实际上,使用SELECT后跟DELETE会做更多的工作。
当然,Hibernate逻辑已被破坏。删除会话将仅查看(并尝试删除)已提交的事务。如果FRED已为客户插入订单,但未提交,则JOHN的删除(通过触发器)将不会看到它或尝试删除它。但它仍将“成功”并尝试删除父客户。 如果您实际上已在数据库中启用了外键约束,则Oracle将启动。它将等待FRED提交,然后拒绝删除,因为它有一个子项。 如果没有外键约束,您可以订购不存在的客户。这就是为什么你应该在数据库中强制执行这种业务逻辑。
答案 1 :(得分:2)
如果可能,请相应地修改和设置数据库表。 - 如果您有DBA,请让DBA参与。
您需要使用Foreign Key constraints and cascade deletes。 这消除了对触发器等的需求......
答案 2 :(得分:0)
您可以查询特殊的dba_objects表:
DECLARE
X NUMBER;
BEGIN
SELECT COUNT(*) INTO X FROM DBA_OBJECTS WHERE OBJECT_TYPE = 'TRIGGER' AND OBJECT_NAME = 'YOUR_TRIGGER_NAME_HERE';
IF X = 0 THEN
--Trigger doesn't exist, OK to delete...
END IF;
END;
答案 3 :(得分:0)
select * from Tab where Tname = "TABLENAME"
如果此查询返回任何行,则表存在,否则不存在。