如何将不同的对象类型实现为相似的表?

Mik*_*ike 5 performance database-design

我有一个我正在尝试设计的数据库。我试图确定声明相似但不同类型的对象的最佳方法,每个对象都有自己的属性集(也许对象之间的某些属性相同)。

比方说,例如,我正在构建一个商城网络应用程序。我想为店主建立一个设施来注册他们的商店、商店类型和该商店的一些特定信息。我面临的问题是对不同商店类型进行建模的最佳方法以及如何根据商店类型合并数据存储模型。

为了使用一些具体数据进一步扩展示例(让我们假设这些信息对于存储都是必需的),模拟这样的事情的最佳方法是什么:

泰国美食
店铺类型: FoodShop
最受欢迎的项目:Pad Thai 
上周访客:368
防静电腕带修复
店铺类型:维修店
当前的电脑维修:26
维修时间估计(以营业时间计算):4 
上周访客:182
电脑
店铺类型:零售店
下次促销日期:2015 年 1 月 2 日
当周销售预估:122418
上周访客:411

假设存在这些商店类型的许多其他实例,每种类型存储相同的数据。为每种商店类型设置一个表格,使用单个表格来表示所有商店类型(使用通用数据)更有意义,还是有更好的方法?

Sol*_*zky 7

假设应用程序将在某些操作(不关心它是什么类型的商店的操作)中以相同的方式处理这些不同的商店类型,那么我的首选方法是使用子类/继承模型。我在其他几个答案中详细说明了这一点:

基本概念如下(使用 Microsoft SQL Server T-SQL 语义)。

首先,您需要主实体表。它代表各种“类型”,因此需要在查找表中定义这些“类型”(并且查找表应enum在应用程序层中进行匹配)。请注意,我在这里使用的是 TINYINT,它保存 0 到 255 之间的值。使用较小的数字类型以满足您的需要。

CREATE TABLE dbo.ShopType
(
  ShopTypeID TINYINT NOT NULL PRIMARY KEY, -- NO IDENTITY / auto-increment!
  ShopType   VARCHAR(50) NOT NULL
);

CREATE TABLE dbo.Shop
(
  ShopID     INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
  ShopTypeID TINYINT NOT NULL REFERENCES dbo.ShopType (ShopTypeID), -- FK to ShopType
  ShopName   NVARCHAR(100) NOT NULL,
  VisitorsLastWeek INT NOT NULL DEFAULT (0),
  -- {OtherCommonFields},...
  CreateDate DATETIME NOT NULL DEFAULT (GETDATE()), -- or GETUTCDATE()
  ModifiedDate DATETIME NOT NULL DEFAULT (GETDATE()) -- or GETUTCDATE()
);
Run Code Online (Sandbox Code Playgroud)

接下来,您为每个特定的“类型”创建一个子类表。有时为多个“类型”共享一个子类表是合适的,但在这样做时要小心,这样一种类型的演变不会与可能共享相同子类表的其他类型不同。请注意,子类表的 PK 与父类(即[Shop]表)中的 PK 字段相同,甚至与它的 FK 相同。原因是两个表中的行(例如[Shop][ShopRepair]具有相同的值)[ShopID]一起是一个完整的实体;子类表中的行本身不代表任何东西,不需要单独的 ID .

CREATE TABLE dbo.ShopFood
(
  ShopID INT NOT NULL PRIMARY KEY REFERENCES dbo.Shop(ShopID),
  MostPopularItem  NVARCHAR(50) NULL,
  ModifiedDate DATETIME NOT NULL DEFAULT (GETDATE()) -- or GETUTCDATE()
);

CREATE TABLE dbo.ShopRepair
(
  ShopID INT NOT NULL PRIMARY KEY REFERENCES dbo.Shop(ShopID),
  CurrentComputerRepairs SMALLINT NOT NULL DEFAULT (0),
  RepairEstimatedHours TINYINT NOT NULL DEFAULT (0),
  ModifiedDate DATETIME NOT NULL DEFAULT (GETDATE()) -- or GETUTCDATE()
);

CREATE TABLE dbo.ShopRetail
(
  ShopID INT NOT NULL PRIMARY KEY REFERENCES dbo.Shop(ShopID),
  NextPromotionDate DATETIME NULL,
  CurrentWeekSalesEstimate MONEY NULL,
  ModifiedDate DATETIME NOT NULL DEFAULT (GETDATE()) -- or GETUTCDATE()
);
Run Code Online (Sandbox Code Playgroud)

为了简化 SELECT 操作,您可以针对每种类型创建视图,如果您愿意:

CREATE VIEW dbo.FoodShop AS
SELECT sh.ShopID, sh.ShopTypeID, sf.MostPopularItem
FROM   dbo.Shop sh
INNER JOIN dbo.ShopFood sf
        ON sf.ShopID = sh.ShopID;

CREATE VIEW dbo.RepairShop AS
SELECT sh.ShopID, sh.ShopTypeID, sr.CurrentComputerRepairs, sr.RepairEstimatedHours
FROM   dbo.Shop sh
INNER JOIN dbo.ShopRepair sr
        ON sr.ShopID = sh.ShopID;

CREATE VIEW dbo.RetailShop AS
SELECT sh.ShopID, sh.ShopTypeID, sr.NextPromotionDate, sr.CurrentWeekSalesEstimate
FROM   dbo.Shop sh
INNER JOIN dbo.ShopRetail sr
        ON sr.ShopID = sh.ShopID;
Run Code Online (Sandbox Code Playgroud)

编辑:
我忘了在“审核”字段添加[CreateDate][ModifiedDate]。我现在已将它们添加到上面的表格中。请注意:

  • 这些字段不在[ShopType]表中,因为这里确实没有任何目的,但这有点主观,有些人仍然想知道至少何时创建记录,所以[CreateDate]在那里可能没问题

  • [CreateDate]字段不在子类表中,因为假设这些行是与父记录同时创建的。但是当涉及到更新时,这些可能只是触及两个表中的一个,具体取决于正在更新的字段。如果使用 SQL Server,甚至可以在单个语句中为两个表创建记录,使用OUTPUT如下子句:

    CREATE PROCEDURE dbo.Shop_CreateRepairShop
    (
      @ShopName NVARCHAR(100),
      @CurrentComputerRepairs SMALLINT,
      @RepairEstimatedHours TINYINT,
      @ShopID INT OUTPUT = -1
    )
    AS
    SET NOCOUNT ON;
    
    INSERT INTO dbo.Shop (ShopName, ShopTypeID)
      OUTPUT INSERTED.ShopID, @CurrentComputerRepairs, @RepairEstimatedHours
      INTO   dbo.ShopRepair (ShopID, CurrentComputerRepairs, RepairEstimatedHours)
      VALUES (@ShopName, 2); -- assuming ShopTypeID for "Repair Shop" = 2
    
    SET @ShopID = SCOPE_IDENTITY();
    
    Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

2633 次

最近记录:

10 年,9 月 前