2012-11-26 67 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一樣強制實施約束。幾十名程序員都是對的。其他人已經接觸到一個學費很高的學習經歷。這是一個恥辱,許多人在不瞭解如何正確使用數據庫的情況下進行數據庫建設。 –