Thiết kế cơ sở dữ liệu: Chia nhiều bảng giống nhau, tốt hay xấu?


7

Tôi rất mới về SQL và cơ sở dữ liệu nói chung. Tôi chỉ sử dụng chúng cho các bài tập về nhà thỉnh thoảng nên tôi thậm chí không cố gắng thành thạo chúng.

Tôi có chỗ ngồi tại một nhà hát, chỗ ngồi được chia thành 4 khu vực chính (A, B, C, D). Mỗi khu vực có cùng số hàng và cùng số ghế trên mỗi hàng.

Trong cơ sở dữ liệu của tôi, tôi muốn có Row + SeatNumber làm khóa chính ghép và có một bảng cho mỗi khu vực.

Bây giờ, tôi chưa biết làm thế nào tôi sẽ chọn, nhưng điều tôi muốn hỏi: Nếu tôi làm theo cách này, liệu những lựa chọn của tôi có thể thực hiện được không? Tôi muốn, ví dụ, chọn một vị trí chính xác trong nhà hát (nơi tôi biết khu vực, hàng và số chỗ ngồi).

4 bảng sẽ là một trở ngại? Bạn có thể đưa ra một ví dụ về cách "chọn" như vậy có thể trông như thế nào?

PS Đây là lần đầu tiên của tôi tại trang web, nếu câu hỏi không thuộc về nơi này, vui lòng hướng dẫn tôi đến một trang web phù hợp hơn trong trao đổi ngăn xếp.


2
Bạn nên có một bảng duy nhất với diện tích là một cột khác.
Philᵀᴹ

Tôi cần số ghế và hàng (kết hợp với diện tích) là duy nhất. Điều này sẽ dễ dàng với PK (hàng & ghế) trong các khu vực (bảng) khác nhau Nhưng nếu không thì tôi có thể làm điều này như thế nào? Có UNIITE (khu vực, hàng ghế) làm cho sự kết hợp của 3 duy nhất (không phải mỗi cột riêng lẻ)?
Kalec

Sử dụng một ràng buộc duy nhất
Philᵀᴹ

Câu trả lời:


18

Bạn nên sử dụng một bảng cho việc này, trừ khi bạn cần các ràng buộc nghiêm ngặt hơn.

Mỗi khu vực có cùng số hàng và cùng số ghế trên mỗi hàng.

Giả sử có 5 hàng ở mỗi khu vực và 6 hàng ở mỗi hàng. Bạn muốn sử dụng một cái gì đó dọc theo những dòng này.

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)
);

Để chọn một chỗ ngồi, đặt ba giá trị trong mệnh đề WHERE.

select *
from seats
where area = 'A' and
       row =  1   and
      seat =  2;

Để sử dụng một bảng như thế này để mô hình đặt chỗ ngồi, hãy đặt nó với mọi khu vực, hàng và chỗ ngồi có thể. Sau đó đặt tham chiếu khóa ngoài cho nó.

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)
);

Bạn có thể thấy tất cả các chỗ ngồi cho một hiệu suất với truy vấn này.

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'

Và bạn có thể có được tất cả các chỗ ngồi có sẵn cho một buổi biểu diễn với một cái gì đó dọc theo những dòng này.

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

Theo mặc định, SQL Server sẽ tạo một chỉ mục được nhóm cho một ràng buộc khóa chính. Bạn sẽ muốn suy nghĩ cẩn thận về thứ tự các cột trong các ràng buộc khóa chính của bạn và xem xét thêm các chỉ mục khác. (Đặc biệt vì đầu ra của bạn thường sẽ cần phải được sắp xếp theo khu vực, hàng và chỗ ngồi.)


Cảm ơn bạn rất nhiều cho một câu trả lời chi tiết như vậy. Tôi đã mong đợi một cái gì đó trên dòng "sử dụng một ràng buộc duy nhất" (chỉ cần tìm ra nó cũng hoạt động cho sự kết hợp của hai hoặc nhiều cột nữa).
Kalec

Chất lượng cao và cũng nghĩ ra câu trả lời. Chúc nhiều người trả lời với chất lượng này.
DeepSpace101

2
Cảm ơn, Sid. Tôi hy vọng bạn biết rằng tôi sẽ trích dẫn bạn trên CV của tôi.
Mike Sherrill 'Nhớ lại mèo'

Câu trả lời rất hay :)
christiandev

1
Có, nhiều bảng hơn cho tính toàn vẹn tham chiếu hơn. (Nhưng không có bảng "khu vực". Tuy nhiên, có thể có .) Thông thường, bạn tin tưởng các quản trị viên địa phương ở một mức độ nhất định. Họ có quyền lợi trong việc cẩn thận. Những người nhận đặt chỗ qua điện thoại sẽ không có quyền chèn hoặc cập nhật quyền trên "ghế".
Mike Sherrill 'Nhớ lại mèo'

7

Nếu thông tin cho thực thể chỗ ngồi giống nhau cho mỗi khu vực, thì bạn có thể đơn giản hóa thiết kế bằng cách chỉ có một Seatsbảng với một Areacột.

Trong trường hợp này, truy vấn sẽ trông giống như:

SELECT ... FROM Seats 
WHERE Seats.Area = 'A' 
AND Seats.Row = X 
AND Seats.Number = Y;

Bạn có thể tìm thấy tùy thuộc vào những gì truy cập dữ liệu và công nghệ giao diện người dùng mà bạn đang sử dụng mà làm việc với một khóa chính thay thế là dễ dàng hơn, và chỉ cần thêm một hạn chế duy nhất trên Area, RowNumberkết hợp.


Có, tôi thấy. Điều đó thực sự sẽ tốt hơn nhiều và cách đơn giản hơn. Cảm ơn bạn. Mặc dù tôi phải hỏi: Duy nhất cho 3 cột, điều đó có nghĩa là sự kết hợp của ba cột là duy nhất, không phải mỗi cột riêng lẻ?
Kalec

3
@Kalec Vâng, sự kết hợp là duy nhất. Nếu chúng là duy nhất, bạn không thể có nhiều hơn một chỗ ngồi trên một khu vực!
Branko Dimitrijevic

6

Tại sao bạn không có Bảng Khu vực và thêm ID dưới dạng FK vào bảng chính? Bằng cách này, bạn sẽ không cần phải viết các truy vấn phức tạp và nếu một Khu vực khác được thêm vào, thì bạn chỉ cần thêm một bản ghi vào bảng Khu vực chứ không phải một bảng mới.

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

CREATE TABLE #areas ( Id INT, AreaName VARCHAR(50))

Loại ý tưởng này và bạn có thể buộc toàn vẹn tham chiếu trong đó bạn chỉ có thể thêm Khu vực nếu nó tồn tại trong bảng Khu vực http://en.wikipedia.org/wiki/Referential_integrity


4

Thật đáng suy nghĩ về các loại truy vấn bạn sẽ muốn chạy trên dữ liệu của bạn và cấu trúc của phần còn lại của cơ sở dữ liệu của bạn - điều đó gần như chắc chắn sẽ giúp bạn suy nghĩ thông qua mô hình.

Chẳng hạn, bạn có thể muốn liên kết chỗ ngồi của mình với vé khi bạn bán chỗ cho buổi biểu diễn. Điều đó cho thấy bạn có một bảng gọi là "hiệu suất" và một bảng khác gọi là "vé". Hãy xem xét cấu trúc của "vé" - bạn muốn liên kết nó với chỗ ngồi. Trong thiết kế hiện tại của bạn, khóa ngoại từ "vé" đến "chỗ ngồi" rất xấu - bạn cần bốn cột để lưu trữ này và bạn không thể đảm bảo rằng vé sẽ không có liên kết đến hai chỗ nếu có lỗi một vài nơi.

Điều đó cho thấy rằng các đề xuất từ ​​devdigital và christiandev có lẽ hữu ích hơn.

Bạn cũng có thể muốn tìm hiểu xem bạn có bao nhiêu chỗ ngồi miễn phí cho hiệu suất - một lần nữa, thiết kế hiện tại của bạn sẽ cần truy vấn 4 bảng, trong khi phương án thay thế chỉ yêu cầu một truy vấn duy nhất.

Cuối cùng, nếu bạn muốn thay đổi cách bạn cấu trúc "chỗ ngồi" - ví dụ bằng cách thêm cột "giá mặc định", thiết kế hiện tại của bạn cần bạn thực hiện thay đổi đó ở 4 vị trí; sử dụng một bảng duy nhất có khóa ngoại "khu vực" cho phép bạn thực hiện thay đổi đó chỉ một lần.


Cảm ơn bạn vì câu trả lời. Tôi đồng ý với bạn hết lòng. Vấn đề chính của tôi là tôi không biết làm thế nào để làm cho bảng hoạt động vì tôi muốn hàng + ghế + diện tích là định danh duy nhất (tôi chỉ xem nó là khóa chính) nhưng khu vực phải lặp lại. Bây giờ, nếu tôi biết rằng tôi có thể tạo ra sự kết hợp của ba thứ duy nhất, tôi thậm chí sẽ không đặt câu hỏi, nhưng vì tôi quá mới về điều này, nên câu trả lời đơn giản là không "bật vào".
Kalec

3

Sẽ tốt hơn nếu chỉ giữ một bảng với một cột khu vực

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.