2012-11-26 42 views
3

我需要帮助,使我的数据库设计更好。SQL Server数据库设计和外键混淆

db设计来自旧开发人员,现在我试图通过设置外键来改善设计,所以不会有任何孤儿表。

CASE 1:

这里是故事:

我有表ProductGroup(PG),ProductType(PT),Brand(B),Design(d),以保持的所有具体细节该项目。然后将所有四张桌子组装成一张桌子ProductMaster(PM),在那里他们将被加入并制作一个ProdCd

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

有表中的(该代码将被简化)样品:

  • ProductGroup1, Finished Goods

    • ProductMaster100010010001, 1, 0001, 001, 0001, PC-10 A, ZEN, PLAIN WHITE
    • 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] 
      

      样品是ProdType1, 0001, PC-10 A, Dinner Plate 10 Inch

    • Brand1, 001, ZEN, ZEN
    • Design1, 0001, PLAIN WHITE, NO DECAL PLAIN WHITE

    如果我删除了Design(1, 0001, PLAIN WHITE, NO DECAL PLAIN WHITE),全行ProductMaster将被删除。

    CASE 2:

    我有交易的一个表,具有标题和详细信息。详细信息仅保留表“产品类型”的“ACd”,其中“GCd”始终为1.当修改PG,PT,B,G时,交易记录也用“GCd”= 1修改。

    该表是这样的:

    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] 
    

    样品是:

    • 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)

    如果ProdType1, 0001, PC-10 A, Dinner Plate 10 Inch)的ProductType记录被删除,在PFDtl的记录也被删除。但是如果记录ProdType7, 0001, PC-12 A, Dinner Plate 12 Inch)被删除,PFdtl上的记录没有改变。

    请帮助我,对设计进行评论,

    1. 如何使它更好?
    2. 如何申请外键是可能的?
    3. DB设计的任何建议?
    4. 在CASE 2中,我应该添加列“GCd”以便能够使用外键吗?
    5. 如果ProductType的ProdType必须是唯一的,我应该把它作为 主键(有GCD和ACD)或我只是需要把UNIQUE或不 施加任何限制

    注:

    1. 旧的设计没有任何外键,全部是应用受限
    2. 我添加第二种情况
  • +0

    你的设计对我来说似乎没问题。问题是你现在可以使用外键吗?如果你可以,那么它确定。但是,如果你不能,那么你需要使用触发器。 – polin

    +0

    正如我所看到的,存在相当多的基本设计缺陷,尤其是分配主键时。主键是否已经这样分配,或者您打算以这种方式分配这些键? – Rachcha

    +0

    那么设计是按照原样制作的,简单地说就是“能够工作”。主键就是这样,我想改变任何可能需要的东西,如果它可以改善事情并减少或不产生孤立的表/记录。 –

    回答

    1

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

    声明外键的好处是它限制数据以防止“参照完整性”的丢失,外键的实例引用不存在的主键。这被称为“孤立参考”。一般而言,强制执行参照完整性的好处绝对大于在插入时确保DBMS检查完整性的成本,以及处理被拒绝数据所需的额外编程。

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

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

    +0

    不,他们之前没有声明任何外键,因为他们认为如果通过应用程序进行控制,证明是错误的,就不会有任何孤儿。好吧,那么我需要去追捕孤儿...在第二种情况下,我应该把GCd放在桌子上还是不能放外键? –

    +0

    应用程序代码无法防止孤立的外键?我感到震惊。震惊,我告诉你。 –

    +0

    成千上万的应用程序员认为他们非常小心以避免数据错误,因为完全可以像DBMS一样强制实施约束。几十名程序员都是对的。其他人已经接触到一个学费很高的学习经历。这是一个耻辱,许多人在不了解如何正确使用数据库的情况下进行数据库建设。 –