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 将为主键约束创建聚集索引。您需要仔细考虑主键约束中的列顺序,并考虑添加其他索引。(特别是因为您的输出通常需要按区域、行和座位排序。)
小智 7
如果每个区域的座位实体信息都相同,那么您可以通过只有一张Seats桌子和一Area列来简化设计。
在这种情况下,查询将类似于:
SELECT ... FROM Seats
WHERE Seats.Area = 'A'
AND Seats.Row = X
AND Seats.Number = Y;
Run Code Online (Sandbox Code Playgroud)
您可能会发现,具体取决于您所使用的数据访问和用户界面技术,与代理主键是工作更容易,只需添加上的唯一约束Area,Row和Number组合。
为什么不只有一个区域表并将 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