2010-02-05 66 views
2

我面临的情况是,我有两个表:A和B. B有一个外键到A.为了强制执行检查约束,在表中复制列是否是个好主意?

A有一个“Detailed”列,用于标识其B子项中是否需要其“细节“部分填写。

如果我有我的精益结构,我无法确定B中的记录是否需要填写其“详细信息”部分,即不为空,而不加入A.因此,唯一的方法是为我为了防止有人插入或更新这些记录到一个无效的状态是有一个触发器加入A并检查其“详细”列。

我的感觉是,约束优于触发器,因为除了过滤器外,它们更像数据的事实,而触发器只是过滤器。

我能得到这个通过复制B中的“详细”栏,然后有一个检查约束(详细=“Y”和细节IS NOT NULL)OR(详细=“N”)

思考解决这个问题的最好方法是?

+0

如果您将列复制到表B中,将使其与表A同步吗?将它留在A中并使用触发器。 – 2010-02-05 16:43:32

+0

如果我要走这条路线,我会强制从B到A的外键的同步性。 – 2010-02-05 16:47:00

+0

与FK之间的二者,那么将不可能改变“详细”的值。 – 2010-02-05 18:12:46

回答

3

您提到的所有工具(约束和触发器)只是一种强制数据库中数据一致性的方法。

简单的业务规则,如“始终有一个参考”,“没有NULL”等是强制执行的约束。

更复杂的商业规则,像你在这里提到的那样,应该使用触发器强制执行。

约束条件不比触发条件“更好”或“更差”:它们只是您需要经常实施的规则的捷径。

为了您的任务,只需实施一个触发器。

但是,在Oracle中,约束和触发器都不是以纯集合方式实现的。对于受DML操作影响的每个记录,它们被称为循环。

最有效的方法是创建一个包装,作为所有DML的单一入口点,并检查包装中的Details

+0

好的建议...我已经在使用所有DML操作的软件包,但由于我不是PL/SQL的专家,但我觉得在将我的理解锁定的情况下添加这些约束作为备份是非常合适的机制和隔离水平并不密切。除了甲骨文的指南和谷歌搜索,掌握这些主题的资源的任何建议?谢谢。 – 2010-02-05 16:39:55

0

我会在UI中执行这样的规则。如果您的业务规则变得更加复杂,那么您需要在模型中填充大量冗余列,以便强制执行数据库模式中的所有规则。

+0

然后应用程序错误,不同的流氓应用程序,手动数据更新或错误的脚本进行更改可能会破坏数据。 – 2010-02-05 16:42:35

+0

我目前在几个地方(客户端,服务器,数据库)执行这些规则,但由于我正在使用的应用程序有很多并发用户可能影响相同的数据,我试图消除两个同时请求传递应用层检查,然后将这些记录更改为无效状态。我想我需要锁定数据库记录才能达到这个安全级别,而不是增加额外的列。 – 2010-02-05 16:45:00

+0

只要性能不成问题,在数据库中执行此操作就没有问题,并且会让您放心,您的数据不会被损坏。 – 2010-02-05 17:22:36

2

在数据库级别执行此操作并且Quassnoi的要点都很好,这是正确的。另外,您可能想要调查让此操作的API引用两个表的updatable join view并通过该约束实现约束。

2

在一个理想的世界,Oracle等数据库管理系统将支持“断言”:

create assertion no_more_than_50_per_user as 
check(not exists(select null 
       from a join b on ... 
       where a.detailed = 'Y' 
       and b.details is null 
); 

他们没有,但(而不是没有很好的理由:这将是很难实现它们性能的方式!)

正如Quassnoi所说,可以使用触发器代替 - 但您需要了解多用户环境中的危险。为确保执行一致性,您需要在检查数据时取出锁定以确保不会发生这种情况:

(假定当前记录1有详细='N',但所有关联的B记录都有详细信息不为空)。

user1> Update A set detailed = 'Y' where a_id=1; 

这是有效的,因为所有关联的B行都有非空的细节。

user2> Update B set details = null where a_id=1; 

这有效,因为user1还没有提交,所以user2的触发器看到详细='N'。

user1> commit; 
user2> commit; 

现在你已经损坏了数据。为了防止这种情况,B上的触发器需要选择“更新”行。

0

如果要在B上复制Detailed字段,则可以使用外键来强制执行它,例如, (B.KEYFIELD,B.详细)参考文献(A.KEYFIELD,A.DETAILED)。我并不是疯狂地重复B上的字段,但另一方面,您似乎有与A上存在的B相关的数据。如果您可以从A中移除DETAILED并将其压入B,则设计可能是清洁器。一些额外的细节可能有帮助

分享和享受。

相关问题