SQL Server数据库设计和外键混淆

时间:2012-11-26 09:06:58

标签: sql sql-server database-design ssms sql-server-2008

我需要帮助才能使我的数据库设计更好。

db设计来自旧的开发人员,现在我试图通过尝试放置外键来改善设计,因此不会有任何孤立表。

案例1:

以下是故事:

我有表ProductGroup(PG),ProductType(PT),Brand(B),Design(D)以保留项目的所有具体细节。然后将所有四个表汇编到一个表ProductMaster(PM)中,在这些表中将它们连接起来并生成ProdCd

当删除PG,PT,B,G的任何行时,PM中的所有相关行也将被删除。

有表的样本(代码将被简化):

CREATE TABLE [dbo].[ProductMaster](
    [ProdCd] [varchar](25) NOT NULL,
    [GCd] [varchar](15) NULL,
    [ACd] [varchar](15) NULL,
    [BCd] [varchar](15) NULL,
    [CCd] [varchar](15) NULL,
    [ProdType] [varchar](50) NULL,
    [BrandCd] [varchar](25) NULL,
    [Design] [varchar](150) NULL,
 CONSTRAINT [PK_ProductMaster] PRIMARY KEY CLUSTERED 
(
    [ProdCd] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[ProductGroup](
    [GCd] [varchar](15) NOT NULL,
    [GroupDesc] [varchar](150) NULL,
 CONSTRAINT [PK_ProductGroup] PRIMARY KEY CLUSTERED 
(
    [GCd] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[ProductType](
    [GCd] [varchar](1) NOT NULL,
    [ACd] [varchar](15) NOT NULL,
    [ProdType] [varchar](50) NOT NULL,
    [TypeDesc] [varchar](150) NULL,
 CONSTRAINT [PK_ProductType] PRIMARY KEY CLUSTERED 
(
    [GCd] ASC,
    [ACd] ASC,
    [ProdType] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[Brand](
    [GCd] [char](1) NOT NULL,
    [BCd] [varchar](15) NOT NULL,
    [BrandCd] [varchar](25) NOT NULL,
    [BrandName] [varchar](75) NULL,
 CONSTRAINT [PK_Brand] PRIMARY KEY CLUSTERED 
(
    [GCd] ASC,
    [BCd] ASC,
    [BrandCd] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[Design](
    [GCd] [char](1) NOT NULL,
    [CCd] [varchar](15) NOT NULL,
    [DesignCd] [varchar](25) NOT NULL,
    [DesignDesc] [varchar](150) NULL,
 CONSTRAINT [PK_Design] PRIMARY KEY CLUSTERED 
(
    [GCd] ASC,
    [CCd] ASC,
    [DesignCd] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

样本是:

  • ProductMaster100010010001, 1, 0001, 001, 0001, PC-10 A, ZEN, PLAIN WHITE
  • ProductGroup1, Finished Goods
  • ProdType1, 0001, PC-10 A, Dinner Plate 10 Inch
  • Brand1, 001, ZEN, ZEN
  • Design1, 0001, PLAIN WHITE, NO DECAL PLAIN WHITE

如果我删除Design的{​​{1}}行,(1, 0001, PLAIN WHITE, NO DECAL PLAIN WHITE)中的整行将被删除。

案例2:

我有一个包含标题和详细信息的事务表。详细信息仅保留“ProductType”表中的“ACd”,其中“GCd”始终为1.当PG,PT,B,G被修改时,事务上的记录也会修改为“GCd”= 1。

表格如下:

ProductMaster

样本是:

  • PFHdr(201211-00001,00001,2012-11-26,1,10,0,10)
  • PFDtl(201211-00001,0001,5,0,5)
  • PFDtl(201211-00001,0002,5,0,5)

如果删除了CREATE TABLE [dbo].[PFHdr]( [FNO] [varchar](25) NOT NULL, [FMO] [varchar](6) NULL, [FDate] [datetime] NULL, [GCd] [int] NULL, *This is group related to the transcation not with the PM [IQtyc] [float] NULL, [RQtyc] [float] NULL, [TQtyc] [float] NULL, CONSTRAINT [PK_PFrmHdr] PRIMARY KEY CLUSTERED ( [FNO] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] CREATE TABLE [dbo].[PFDtl]( [FNO] [varchar](25) NOT NULL, [ACd] [varchar](15) NOT NULL, [Input] [float] NULL, [Reject] [float] NULL, [Transfer] [float] NULL, CONSTRAINT [PK_PFrmDtl] PRIMARY KEY CLUSTERED ( [FNO] ASC, [ACd] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] ProdType)的ProductType记录,则PFDtl上的记录也会被删除。但是如果记录1, 0001, PC-10 A, Dinner Plate 10 InchProdType)被删除,则PFdtl上的记录没有改变。

请帮帮我,评论设计,

  1. 如何让它变得更好?
  2. 如何申请外键?
  3. DB设计的任何建议?
  4. 在案例2中,我应该添加“GCd”列才能使用外键吗?
  5. 如果ProductType上的ProdType必须是唯一的,我应该将其用作 主键(使用GCd和ACd)或者我只需要放置UNIQUE 提出任何限制
  6. 注意:

    1. 旧设计没有任何外键,都是应用程序限制
    2. 我添加第二个案例

1 个答案:

答案 0 :(得分:1)

这里真的有两个问题。外键是否存在?如果存在外键,是否会声明?当我读取你的模式时,那里有一些外键,例如ProductMaster.GCd。他们只是没有宣布。

声明外键的优点是它约束数据以防止丢失“引用完整性”,即外键实例引用不存在的主键的情况。这称为“孤立引用”。一般而言,强制引用完整性的优势绝大于在插入时使DBMS检查完整性的成本,以及处理被拒绝数据所需的额外编程。

如果要向现有数据库添加参照完整性约束,则可能必须在DBMS允许您放入约束之前找到并处理“孤立引用”。这通常涉及大量使用“WHERE NOT EXISTS”结构。

以前的开发人员在开始时没有声明外键太糟糕了。