2

我正在研究制造数据库的一部分。该业务接受定制订单并根据规格构建项目。他们只构建了几种(比如说 3-10 种)类型的对象,但每种类型的对象在记录的规范中都是不同的。我想要一个主制造表 (mfgorders) 列出一些常见字段,然后让它引用特定于订购实体的规格表。我不完全相信这是正确的方法。事实上,我一点也不自信。我所有的其他建模都是直截了当的,但是这个让我很烦。

这是SQL:

CREATE TABLE dbo.mfgorders (MfgOrderId int NOT NULL
                                       IDENTITY (1, 1) ,
                        OrderId int NOT NULL,
                        LineNbr tinyint NOT NULL,
                        MfgTypeId tinyint NOT NULL,
                        ItemDescription varchar (999) ,
                        ManufacturingCost smallmoney,
                        CONSTRAINT PK_mfgorders PRIMARY KEY (MfgOrderId)) ;
--OrderId + LineNbr are a composite referencing a row on a lineitem table (not depicted here)

CREATE TABLE dbo.mfgorders_entity1 (MfgOrderId int NOT NULL,
                                EntitySize decimal (5, 3) ,
                                Width decimal (4, 2) ,
                                Thickness decimal (4, 2) ,
                                CONSTRAINT PK_mfgorders_entity1 PRIMARY KEY (MfgOrderId)) ;

CREATE TABLE dbo.mfgorders_entity2 (MfgOrderId int NOT NULL,
                                Height decimal (5, 2) ,
                                Width decimal (5, 2) ,
                                Thickness decimal (4, 2) ,
                                RotationSetting decimal (4, 1) ,
                                FinishedHeight decimal (5, 2) ,
                                FinishedWidth decimal (5, 2) ,
                                FinishedThickness decimal (4, 2) ,
                                CONSTRAINT PK_mfgorders_entity2 PRIMARY KEY (MfgOrderId)) ;

CREATE TABLE mfg_types (MfgTypeId tinyint NOT NULL,
                    ItemName varchar (32) NOT NULL,
                    ItemDescription nvarchar (64) NULL,
                    IsActive bit NOT NULL
                                 CONSTRAINT DF_mfg_types_IsActive DEFAULT 1,
                    SortOrder int NULL,
                    CONSTRAINT PK_mfg_types PRIMARY KEY (MfgTypeId)) ;

ALTER TABLE dbo.mfgorders_entity1 ADD CONSTRAINT FK_mfgorders_entity1_mfgorders FOREIGN KEY (MfgOrderId) REFERENCES dbo.mfgorders (MfgOrderId) ON UPDATE NO ACTION ON DELETE CASCADE;

ALTER TABLE dbo.mfgorders_entity2 ADD CONSTRAINT FK_mfgorders_entity2_mfgorders FOREIGN KEY (MfgOrderId) REFERENCES dbo.mfgorders (MfgOrderId) ON UPDATE NO ACTION ON DELETE CASCADE;

ALTER TABLE dbo.mfgorders ADD CONSTRAINT FK_mfgorders_mfg_types FOREIGN KEY (MfgTypeId) REFERENCES dbo.mfg_types (MfgTypeId) ON UPDATE NO ACTION ON DELETE CASCADE;

这是上述代码的 ER 图:

ER图

该模型意味着 entity1 和 entity2 可以具有相同的 MfgOrderId,我当然不希望这样。我希望 MfgOrderId 仅引用其中一个实体。我认为在我的脑海中我希望利用 mfg_types 指向正确的实体表,但我觉得模型已经关闭,我会通过询问 SO 社区来增加几年的生活。

问候,约翰

4

3 回答 3

2

“……我当然不想这样。”

我不一定会跳到那个结论。您描述的模型是可接受的模型,Hibernate 称它为InheritanceType.JOINED您可以在他们的 docs中阅读有关它的信息,但您会使用共享相同 ID 的所有表来建模这种关系。

JPA 文档也谈到了它。

使用它的关键部分,或者实际上是关于在数据库中表示类层次结构的关键部分,是您需要能够判断您是否拥有实体 1 或实体 2。最明确的方法是使用Discriminator,基本上是超类表中的一列,表示任何行代表实体 1 或实体 2。

我相信,如果您没有指定鉴别器,并且您使用的是 JOINED,那么 Hibernate(可能还有其他 JPA 实现)将通过检查所有子类表并查看哪个包含具有特定 ID 的行来自动为您完成. 假设每个 MfgOrderId 都在一个且只有一个子类表中,这将在不更改架构的情况下为您工作。

编辑

我错误地切换了 TABLE_PER_CLASS,我的意思是加入了!

于 2013-02-14T19:32:35.920 回答
1

你的设计表达或试图表达的是超类型和子类型的关系。

表达这一点的一种方法是MfgTypeId在每个实体表中包含该字段:

CREATE TABLE dbo.mfgorders_entity2 (MfgOrderId int NOT NULL,
                 MfgTypeId tinyint NOT NULL,
                 Height decimal (5, 2) ,
                 Width decimal (5, 2) ,
                 Thickness decimal (4, 2) ,
                 RotationSetting decimal (4, 1) ,
                 FinishedHeight decimal (5, 2) ,
                 FinishedWidth decimal (5, 2) ,
                 FinishedThickness decimal (4, 2) ,
                 CONSTRAINT PK_mfgorders_entity2 PRIMARY KEY (MfgOrderId, MfgTypeId),
                 CONSTRAINT chkEntity2_MfgTypeID CHECK (MfgTypeId = 'Type Id for Entity 2')) ;

我可能还会更改MfgOrders表以将 MfgTypeId 也包含在主键中。

CREATE TABLE dbo.mfgorders (MfgOrderId int NOT NULL IDENTITY (1, 1) ,
                 MfgTypeId tinyint NOT NULL,                 
                 OrderId int NOT NULL,
                 LineNbr tinyint NOT NULL,
                 ItemDescription varchar (999) ,
                 ManufacturingCost smallmoney,
                 CONSTRAINT PK_mfgorders PRIMARY KEY (MfgOrderId, MfgTypeId)) ;

如果您搜索超类型和子类型数据库建模,您会发现许多资源,包括关于 SO 和 Stackexchange 网络的问题。我在下面提供了一些链接,这些链接可能会帮助您开始使用:

  1. 数据库管理员的超类型/子类型

  2. 超类型和子类型

  3. 如何在子类型中实现引用完整性

于 2013-02-14T19:52:41.943 回答
0

我看不出你所拥有的任何重大问题。这是我可能会做的:

CREATE TABLE dbo.mfgorders (    MfgOrderId int NOT NULL IDENTITY (1, 1),
                            OrderId int NOT NULL,
                            LineNbr tinyint NOT NULL,
                            MfgTypeId tinyint NOT NULL,
                            ItemDescription varchar (999) ,
                            ManufacturingCost smallmoney,
                            CONSTRAINT PK_mfgorders PRIMARY KEY (MfgOrderId)) ;
--OrderId + LineNbr are a composite referencing a row on a lineitem table (not depicted here)

CREATE TABLE dbo.mfgorders_entity1( MfgOrderEntity1Id int NOT NULL IDENTITY (1, 1),
                                MfgOrderId int NOT NULL,
                                EntitySize decimal (5, 3) ,
                                Width decimal (4, 2) ,
                                Thickness decimal (4, 2) ,
                                CONSTRAINT PK_mfgorders_entity1 PRIMARY KEY (MfgOrderEntity1Id)) ;

CREATE TABLE dbo.mfgorders_entity2 (MfgOrderEntity2Id int NOT NULL IDENTITY (1, 1),
                                MfgOrderId int NOT NULL,
                                Height decimal (5, 2) ,
                                Width decimal (5, 2) ,
                                Thickness decimal (4, 2) ,
                                RotationSetting decimal (4, 1) ,
                                FinishedHeight decimal (5, 2) ,
                                FinishedWidth decimal (5, 2) ,
                                FinishedThickness decimal (4, 2) ,
                                CONSTRAINT PK_mfgorders_entity2 PRIMARY KEY (MfgOrderEntity2Id)) ;

CREATE TABLE mfg_types (            MfgTypeId tinyint NOT NULL,
                                ItemName varchar (32) NOT NULL,
                                ItemDescription nvarchar (64) NULL,
                                IsActive bit NOT NULL
                                CONSTRAINT DF_mfg_types_IsActive DEFAULT 1,
                                SortOrder int NULL,
                                CONSTRAINT PK_mfg_types PRIMARY KEY (MfgTypeId)) ;

ALTER TABLE dbo.mfgorders_entity1 ADD CONSTRAINT FK_mfgorders_entity1_mfgorders FOREIGN KEY (MfgOrderId) REFERENCES dbo.mfgorders (MfgOrderId) ON UPDATE NO ACTION ON DELETE CASCADE;

ALTER TABLE dbo.mfgorders_entity2 ADD CONSTRAINT FK_mfgorders_entity2_mfgorders FOREIGN KEY (MfgOrderId) REFERENCES dbo.mfgorders (MfgOrderId) ON UPDATE NO ACTION ON DELETE CASCADE;

ALTER TABLE dbo.mfgorders ADD CONSTRAINT FK_mfgorders_mfg_types FOREIGN KEY (MfgTypeId) REFERENCES dbo.mfg_types (MfgTypeId) ON UPDATE NO ACTION ON DELETE CASCADE;
于 2013-02-14T19:40:14.437 回答