数据库设计:划分多个相同的表,好还是坏?

Kal*_*lec 7 database-design sql-server

总的来说,我对 SQL 和数据库很陌生。我只将它们用于偶尔的家庭作业,所以我什至没有尝试掌握它们。

我在剧院有座位,座位分为 4 个主要区域(A、B、C、D)。每个区域都有相同的行数和相同的每行座位数。

在我的数据库中,我希望将 Row + SeatNumber 作为复合主键,并为每个区域设置一个表。

现在,我还不知道我将如何做我的选择,但我想问的是:如果我这样做,我的选择是否可行?例如,我想在剧院内选择一个确切的位置(我知道区域、行和座位号的位置)。

4张桌子会成为障碍吗?你能举一个例子来说明这种“选择”的样子吗?

PS 这是我第一次来这个站点,如果问题不属于这里,请指导我到堆栈交换中更合适的站点。

Mik*_*ll' 18

您应该为此使用一张表,除非您需要更严格的约束。

每个区域都有相同的行数和相同的每行座位数。

假设每个区域有 5 排,每排 6 个座位。你想使用这些方面的东西。

create table seats (
  area char(1) not null check (area in ('A', 'B', 'C', 'D')),
  row integer not null check ( row between 1 and 5 ),
  seat integer not null check ( seat between 1 and 6 ),
  primary key (area, row, seat)
);
Run Code Online (Sandbox Code Playgroud)

要选择一个座位,请在 WHERE 子句中放置三个值。

select *
from seats
where area = 'A' and
       row =  1   and
      seat =  2;
Run Code Online (Sandbox Code Playgroud)

要使用这样的表来模拟座位预订,请在其中填充所有可能的区域、行和座位。然后为其设置外键引用。

create table reservations (
  performance_time datetime not null,
  party_name varchar(40) not null,
  area char(1) not null,
  row integer not null,
  seat integer not null,
  primary key (performance_time, party_name, area, row, seat),
  foreign key (area, row, seat) references seats (area, row, seat)
);
Run Code Online (Sandbox Code Playgroud)

您可以使用此查询查看演出的所有座位。

select s.area, s.row, s.seat, r.performance_time, r.party_name
from seats s
left join reservations r
       on r.area = s.area and
          r.row  = s.row  and
          r.seat = s.seat and
          r.performance_time = '2013-04-30 08:00 pm'
Run Code Online (Sandbox Code Playgroud)

您可以通过这些方式获得所有可用的表演席位。

with seating as (
  select s.area, s.row, s.seat, r.performance_time, r.party_name
  from seats s
  left join reservations r
         on r.area = s.area and
            r.row  = s.row  and
            r.seat = s.seat and
            r.performance_time = '2013-04-30 08:00 pm'
)
select *
from seating
where performance_time is null
Run Code Online (Sandbox Code Playgroud)

默认情况下,SQL Server 将为主键约束创建聚集索引。您需要仔细考虑主键约束中的列顺序,并考虑添加其他索引。(特别是因为您的输出通常需要按区域、行和座位排序。)

  • 谢谢你,希德。我希望你知道我会在我的简历中引用你。 (2认同)

小智 7

如果每个区域的座位实体信息都相同,那么您可以通过只有一张Seats桌子和一Area列来简化设计。

在这种情况下,查询将类似于:

SELECT ... FROM Seats 
WHERE Seats.Area = 'A' 
AND Seats.Row = X 
AND Seats.Number = Y;
Run Code Online (Sandbox Code Playgroud)

您可能会发现,具体取决于您所使用的数据访问和用户界面技术,与代理主键是工作更容易,只需添加上的唯一约束AreaRowNumber组合。

  • @Kalec 是的,**组合** 是独一无二的。如果它们是独一无二的,那么每个区域最多只能有一个座位! (3认同)

chr*_*dev 6

为什么不只有一个区域表并将 ID 作为 FK 添加到主表中?这样你就不需要编写复杂的查询,如果添加了另一个区域,那么你只需要向区域表添加一条记录,而不是新表。

CREATE TABLE #seats
    (
      Id INT ,
      SeatRow INT ,
      SeatNumber INT ,
      AreaId INT
    )

CREATE TABLE #areas ( Id INT, AreaName VARCHAR(50))
Run Code Online (Sandbox Code Playgroud)

这种想法,你可以强制参照完整性,如果它存在于 Areas 表中,你只能添加一个区域http://en.wikipedia.org/wiki/Referential_integrity