为包,产品和服务创建方案

时间:2017-03-24 12:49:01

标签: sql sql-server

我有3个表:包,产品和服务:

create table dbo.Packages ( 
  Id int identity not null
  Name nvarchar (80) not null
)

create table dbo.Products ( 
  Id int identity not null
  Name nvarchar (80) not null
)

create table dbo.Services ( 
  Id int identity not null
  Name nvarchar (80) not null
)

我需要将3个表联系起来以满足以下要求:

  1. 一揽子计划包含各种产品和服务;
  2. 所有产品都可以包含在包装中;
  3. 并非所有服务都可以包含在包中;
  4. 产品或服务可以包含在许多包中;
  5. 产品或服务不能在同一个包中出现两次。
  6. 由于(3)和(5),我不确定如何建立这个方案。

    我可能需要Table继承,多对多关系和某种索引(5)?

    有人可以就此提出建议吗?

    更新

    Frazz建议的一个选项是使用Component base table,如下所示,Service可以将ComponentId作为null。还有一个选择...

    CREATE TABLE dbo.Packages ( 
      id INT IDENTITY NOT NULL,
      name NVARCHAR(80) NOT NULL,
      PRIMARY KEY (id)
    );
    
    CREATE TABLE dbo.Components ( 
      id INT IDENTITY NOT NULL,
      PRIMARY KEY (id)
    );
    
    CREATE TABLE dbo.Products ( 
      id INT IDENTITY NOT NULL,
      component_id INT NOT NULL,
      name NVARCHAR(80) NOT NULL
      PRIMARY KEY (id)
    );
    
    CREATE TABLE dbo.Services ( 
      id INT IDENTITY NOT NULL,
      component_id INT NULL,
      name NVARCHAR(80) NOT NULL,
      PRIMARY KEY (id)
    );
    
    CREATE TABLE dbo.Package_Components (
      package_id INT NOT NULL REFERENCES Packages(id),
      component_id INT NOT NULL REFERENCES Components(id)
      PRIMARY KEY (package_id, component_id)
    );
    

1 个答案:

答案 0 :(得分:2)

以下内容应解决您提出的大部分内容(在SQLFiddle上测试):

CREATE TABLE dbo.Packages ( 
  id   INT IDENTITY NOT NULL,
  name NVARCHAR(80) NOT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE dbo.Products ( 
  id   INT IDENTITY NOT NULL,
  name NVARCHAR(80) NOT NULL
  PRIMARY KEY (id)
);

CREATE TABLE dbo.Services ( 
  id              INT IDENTITY NOT NULL,
  name            NVARCHAR(80) NOT NULL,
  can_be_packaged BIT          NOT NULL
  PRIMARY KEY (id)
);

CREATE TABLE dbo.Package_Products (
  package_id INT NOT NULL REFERENCES Packages (id),
  product_id INT NOT NULL REFERENCES Products (id)
  PRIMARY KEY (package_id, product_id)
);

CREATE TABLE dbo.Package_Services (
  package_id INT NOT NULL REFERENCES Packages (id),
  service_id INT NOT NULL REFERENCES Services (id)
  PRIMARY KEY (package_id, service_id)
);

另外两个表Package_Products和Package_Services实现了(1),(2)和(4)所需的多对多关系。他们的主键强制执行(5)。

剩下的是你的要求(3)。您说这完全取决于服务,因此额外的BIT列can_be_packaged是处理需求的好方法。但是你需要强制执行它。

问题是您无法在CHECK约束中执行SQL语句。所以我看到的唯一解决方案是在Package_Services表上有一个TRIGGER FOR INSERT和一个TRIGGER FOR UPDATE。这些触发器应该在Services表上执行SELECT并检查can_be_packaged位是否为。