我试图在多个表的ORACLE数据库中强制执行CHECK约束
CREATE TABLE RollingStocks (
Id NUMBER,
Name Varchar2(80) NOT NULL,
RollingStockCategoryId NUMBER NOT NULL,
CONSTRAINT Pk_RollingStocks Primary Key (Id),
CONSTRAINT Check_RollingStocks_CategoryId
CHECK ((RollingStockCategoryId IN (SELECT Id FROM FreightWagonTypes))
OR
(RollingStockCategoryId IN (SELECT Id FROM LocomotiveClasses)))
);
...但我收到以下错误:
*原因:声明中不允许使用子查询。 *操作:从语句中删除子查询。
您能帮助我了解问题是什么或如何获得相同的结果吗?
答案 0 :(得分:2)
Oracle中的检查约束非常有限。要按照您的建议进行检查,您必须实施PL/SQL trigger。
我的建议是完全避免触发器。实现修改数据库并包含检查的存储过程。存储过程更容易维护,但实现起来稍微困难一些。但是从长期来看,将前端从直接表访问更改为存储过程访问可以多次回报。
答案 1 :(得分:2)
您要做的是确保插入一个表中的值存在于另一个表中,即强制执行外键。那就是:
CREATE TABLE RollingStocks (
...
CONSTRAINT Pk_RollingStocks Primary Key (Id),
CONSTRAINT RollingStocks_CategoryId_FK (RollingStockCategoryId )
REFERENCES FreightWagonTypes (ID)
);
除了您要强制引用两个表的外键之外。这是不可能做到的。
你有几个选择。一种方法是将FreightWagonTypes和LocomotiveClasses合并为一个表。如果您需要为应用程序的其他部分使用单独的表,则可以构建物化视图以强制执行外键。物化视图类似于表,可以通过外键引用。如果两个表的键值发生冲突,则此选项将不起作用。
另一个选择是认识到两个候选参考表的存在表明RollingStock可能需要分成两个表 - 或者可能三个:超级型和两个子型表,即RollingStock和FreightWagons,Locomotives。
那么,PassengerCoaches,GuardsWagons和RestaurantCars呢?
答案 2 :(得分:0)
不幸的是,Oracle不支持这样的复杂检查约束。
在这种情况下,您最好的选择是稍微更改数据模型 - 在FreightWagonTypes
和LocomotiveClasses
上添加父表,这将保留这两个表中的所有ID。这样,您就可以将FK添加到单个表中。