Tư vấn về thiết kế cơ bản, thiết kế cơ sở dữ liệu lần đầu tiên


8

Tôi đang tham gia một khóa học để trở thành một nhà phát triển Java.

Khóa học liên quan đến việc sử dụng cơ sở dữ liệu nhưng chúng tôi không bao giờ thực sự thiết kế bất kỳ, thật không may.

Hầu hết thời gian chúng tôi nhận được cơ sở dữ liệu được tạo sẵn và chúng tôi phải triển khai mã trên đó để Chèn, Cập nhật, Đọc hoặc Xóa dữ liệu.

Nhưng khi thử nghiệm cuối cùng của tôi đến, rất có thể tôi sẽ tạo ra thứ gì đó liên quan đến cơ sở dữ liệu và do đó tôi muốn thử thiết kế một vài cái nhỏ hơn để có được thiết kế vì tôi nhận thấy rằng một thiết kế cơ sở dữ liệu tốt tạo ra nhiều sự khác biệt khi viết mã để làm việc với nó.

Tôi hy vọng những loại câu hỏi này được cho phép ở đây và nó sẽ không quá rộng.


Đây là một thiết kế nhỏ tôi đã làm cho một cái gì đó đơn giản như clubsmembersvới addressesphonenumbers.

  • Sẽ có nhiều câu lạc bộ.
  • Mỗi câu lạc bộ sẽ có nhiều thành viên (hiển nhiên)
  • Một thành viên không thể là một phần của nhiều câu lạc bộ
  • Một thành viên có thể có nhiều máy phát âm và địa chỉ email
  • Một thành viên chỉ có thể có một địa chỉ
  • Một địa chỉ có thể thuộc về các thành viên khác nhau (cặp vợ chồng hoặc anh chị em)

Những nhầm lẫn lớn nhất của tôi:

  • Nếu tôi muốn thêm một cột trong Clubđó mô tả chủ sở hữu, người cũng sẽ là thành viên, cách tiếp cận tốt nhất mà không có cùng một thành viên được liệt kê hai lần là gì?

  • Tôi có nên đặt tất cả các bảng của mình lên mức tăng tự động của id hay đây sẽ là một ý tưởng tồi? (lợi ích / nhược điểm?)

  • Nếu tôi thêm khóa ngoại trong tab khóa ngoại, chúng sẽ tự động tương ứng với bảng chính xác hay tôi cũng phải thêm chúng vào các cột? (xem hình 2)

  • Và câu hỏi có lẽ khó hiểu nhất của tôi ... Tôi có đặt các khóa ngoại phonenumberemailtrong bảng tương ứng của họ liên kết với một người hay tôi nên đặt số điện thoại và số email của Id vào bảng người?

(Tôi xin lỗi vì ngôn ngữ trong ảnh không phải là tiếng Anh, tôi hy vọng đây không phải là vấn đề quá lớn)

Thiết kế

Khóa ngoại

Câu trả lời:


11

Trả lời các câu hỏi cá nhân của bạn

Nếu tôi muốn thêm một cột trong Clubđó mô tả chủ sở hữu, người cũng sẽ là thành viên, cách tiếp cận tốt nhất mà không có cùng một thành viên được liệt kê hai lần là gì?

Nếu như đã nêu trong các thông số kỹ thuật của bạn a Person can be a Member of only one Club, và bạn quan tâm đến việc lưu trữ dữ liệu này đơn giản là đúng hoặc sai , một tùy chọn là thêm một BIT(1)hoặc một cột BOOLEAN( TINYINT) vào Personbảng và bạn có thể muốn gọi cột này IsClubOwner. Bằng cách này, bạn có thể đăng ký thực tế rằng một người xác định là chủ sở hữu câu lạc bộ chỉ một lần. Ngoài ra, phương pháp này cũng cho phép khả năng giữ lại một số ngườichủ sở hữu của cùng một câu lạc bộ . Bạn có thể thấy mô tả mức logic của phương pháp này trong Hình 1 .

Tuy nhiên, bạn đang tìm kiếm cách tiếp cận tốt nhất và theo kinh nghiệm của tôi, cách tiếp cận như vậy đòi hỏi sự phát triển của một cấu trúc linh hoạt và có thể mở rộng hơn nhiều. Về mặt này, hãy theo dõi sự tiến triển của một bài tập mô hình hóa cho những điểm này và các điểm khác bên dưới, trong các phần có tiêu đề Bao gồm các thông số kỹ thuật còn lại của bạn.

Tôi có nên đặt tất cả các bảng của mình lên mức tăng tự động của một idhoặc đây sẽ là một ý tưởng tồi? (lợi ích / nhược điểm?)

Nếu bạn phải đối mặt với một rõ ràng yêu cầu cho biết định nghĩa của một bảng với một cột các đặc điểm như vậy, và cột mà có một ý nghĩa ngữ cảnh hợp lệ hoặc phục vụ một mục đích cụ thể như là một thay thế cho một rộng PRIMARY KEY tự nhiên (PK), sau đó có, bạn nên tiến hành theo cách đó

Mặt khác, nếu bạn không có yêu cầu, tôi cho rằng nó sẽ không cần thiết vì bạn phải lưu trữ và quản lý một cột bổ sung vô nghĩa và (có lẽ?) Cũng là một INDEX bổ sung trong cơ sở dữ liệu của bạn.

Như thường lệ, bạn phải phân tích từng trường hợp cùng với hậu quả chung của nó để quyết định cách tiếp tục.

Nếu tôi thêm khóa ngoại trong tab khóa ngoại, chúng sẽ tự động tương ứng với bảng chính xác hay tôi cũng phải thêm chúng vào các cột?

Về vấn đề này, lời khuyên của tôi dành cho bạn là tạo cấu trúc cơ sở dữ liệu theo cách thủ công, mã hóa các DDLcâu lệnh của riêng bạn cho đến khi bạn nắm vững chủ đề. Nếu bạn làm như vậy, sẽ dễ dàng hơn cho bạn để hiểu các quy trình mà các công cụ đồ họa đang thực hiện trên hệ thống điều khiển trực tuyến.

Đối với tôi, ví dụ, tạo một tuyên bố như sau:

CONSTRAINT FK_PersonPhoneNumber_to_Person FOREIGN KEY (PersonId)
REFERENCES Person (PersonId)

Được hướng dẫn nhiều hơn so với việc sử dụng các công cụ GUI để thực hiện loại nhiệm vụ này, đặc biệt là bây giờ bạn đang xây dựng các thiết kế đầu tiên của mình.

Và câu hỏi có lẽ khó hiểu nhất của tôi trong tất cả ... Tôi có đặt các khóa ngoại của phone_numberemailtrong bảng tương ứng của chúng liên kết với một person_idhoặc tôi nên đặt phone_numberemail idstrong bảng người không?

Cá nhân, tôi nghĩ rằng điều này và tất cả các câu hỏi khác của bạn là hoàn toàn hợp lệđược bối cảnh hóa tốt .

Quay trở lại các khía cạnh kỹ thuật liên quan đến chúng tôi, cuộc điều tra chính xác này cung cấp một cơ hội tốt để xem xét hai khẳng định sau:

  • A Person can be reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber can be used to reach one-to-many People

Vì vậy, người ta có thể kết luận rằng có một mối quan hệ nhiều-nhiều giữa PersonPhoneNumberdo đó, tôi đề nghị tạo ra một bảng kết hợp có tên PersonPhoneNumberđể thể hiện mối quan hệ đã nói trong cơ sở dữ liệu của bạn. PK của bảng này phải được tạo bởi hai cột khác nhau: PersonId(một NGOẠI TỆ [FK] trỏ đến Person.PersonId) và PhoneNumber(một FK tạo tham chiếu đến PhoneNumber.Number). Để biết mô tả mức logic của tất cả các mục trên, xem Hình 1 .

Mặt khác, chúng ta hãy xem xét hai mệnh đề sau:

  • A Person can be contacted via zero-one-or-many EmailAddresses
  • An EmailAddress can be used to contact exactly one Person

Sau đó, vâng, bạn nên đặt tham chiếu FK Persontừ EmailAddressbảng và bảng này cũng có PK tổng hợp, bao gồm các cột PersonIdAddress. Theo cách này, bạn có thể đảm bảo rằng cùng một kết hợp EmailAddress.PersonIdvà chỉ EmailAddress.Addresscó thể được chèn một lần.

Nếu bạn cũng muốn đảm bảo rằng một cái nhất định EmailAddres.Addresscó thể được lưu trữ trong một hàng duy nhất, bạn chỉ cần thiết lập một CONSTRAINT ĐỘC ĐÁO cho cột này.

Mô hình dữ liệu logic được đề xuất

Để đưa ra các đề xuất của tôi rõ ràng hơn, tôi đã đưa vào bốn mô hình logic IDEF1X [1] riêng biệt được hiển thị trong Hình 1 , Hình 2 , Hình 3Hình 4 . Tôi sẽ cung cấp một lời giải thích về các tính năng có liên quan nhất được hiển thị trong mỗi một trong số chúng trong các phần tương ứng. Bạn cũng có thể tải xuống từ Dropbox một bản PDF tích hợp trong một mô hình duy nhất, phần lớn các yếu tố đang thảo luận.

Bao gồm các thông số kỹ thuật còn lại của bạn

Người và địa chỉ liên quan

Hãy để chúng tôi kiểm tra hai xác nhận sau (hơi được điều chỉnh lại) có liên quan đến mọi ngườiđịa chỉ :

  • A Person can only have one Address
  • An Address can belong to different People (couples or siblings)

Vì vậy, để đối phó với các hạn chế này, bạn có thể chọn triển khai mô hình dữ liệu tương tự như mô hình bạn có thể thấy trong Hình 1 .

Hình 1. Mô hình dữ liệu câu lạc bộ và thành viên - Thông số kỹ thuật đầu tiên

Có tính đến mô hình được giới thiệu, bạn nên làm theo các bước tiếp theo:

  1. Tạo một bảng gọi là PersonAddresssửa chữa mối quan hệ giữa PersonAddress. Đặt các cột PersonIdAddressIdlàm PK tổng hợp của bảng này.

  2. Định cấu hình CONSTRAINT ĐỘC ĐÁO cho PersonAddress.PersonIdcột để đảm bảo rằng có thể chèn một giá trị cụ thể vào tối đa một hàng của bảng đã nói. Ở cấp độ logic, tình huống này ngụ ý rằng nó PersonAddress.PersonIdđã trở thành một phím ALTERNATE [2] .

  3. Nếu giá trị của AddressIdmột lần thử xác định PersonAddresschưa được lưu trữ, thì hãy tiếp tục chèn, nếu không, khi giá trị đó đã tồn tại trong một hàng, bạn phải kiểm tra xem (a) PersonIdngười đã đăng ký AddressIdcũng được đăng ký như là Marriage.WifeIdif the PersonIdis a male (datum có nguồn gốc từ Person.GenreCode) hoặc (b) rằng đó PersonIdMarriage.HusbandIdkhi cái PersonIdlà nữ (cũng xuất phát từ đức tính của Person.GenreCode). Nếu một trong những điều kiện này được đáp ứng trong tình huống chiếm đoạt, thì bạn nên để INSERT tiếp tục.

  4. Nếu các điều kiện trên không được đáp ứng, vẫn có cơ hội cho PersonAddressviệc chèn cố gắng thành công. Bạn phải kiểm tra xem PersonIdgiá trị có liên quan đến việc chèn thử nói ít nhất một Progeny.ParentIdvới giá trị PersonIdđã đăng ký PersonAddress.AddressId. Nếu điều kiện này được thỏa mãn, thì điều đó có nghĩa là chúng được lưu trữ như Siblingstrong cơ sở dữ liệu, do đó, INSERT này phải thành công.

Như trong bất kỳ triển khai cơ sở dữ liệu quan hệ nào, bạn nên nghiêm túc xem xét việc thực hiện các DMLhoạt động của mình bên trong Giao dịch ACID để bạn có thể bảo vệ tính toàn vẹnnhất quán của dữ liệu bạn đang làm việc.

Tham dự các yêu cầu bạn đã thêm trong nhận xét: Địa chỉ và số điện thoại phục vụ như nhau Câu lạc bộ và mọi người

Với điều kiện bạn muốn tạo cơ hội cho các địa chỉsố điện thoại để phục vụ cả ngườicâu lạc bộ , bạn có thể sử dụng mối quan hệ siêu kiểu phụ . Dưới đây là một câu trả lời trong đó tôi đưa ra cách xử lý chi tiết hơn cho loại cấu trúc này, trong trường hợp bạn quan tâm.

Trong kịch bản hiện tại, bạn có thể định nghĩa PersonClublà các kiểu con của một thực thể mới có tên Party, một thuật ngữ thường được sử dụng trong vòng tròn pháp lý để đại diện cho (a) một người hoặc (b) một nhóm người (như đã lưu ý trong ý nghĩa số 6 ). Với phương pháp này, các mối quan hệ giữa Addresses(hoặc PhoneNumbers) PeopleClubssẽ được xác định thông qua Party, siêu kiểu. Xem hình 2 cho một mô tả về đề xuất này.

Hình 2. Mô hình dữ liệu câu lạc bộ và thành viên - Thông số kỹ thuật thứ hai

Đảng và địa chỉ

Vì vậy, chúng ta có thể đọc trong mô hình mới này rằng:

  • A Party keeps zero-one-or-many Addresses
  • An Address is kept by one-to-many Parties

Do đó, có một mối quan hệ nhiều-nhiều liên quan PartyAddressđiều đó được thể hiện bằng cách của PartyAddressthực thể.

Tiệc tùng và số điện thoại

Hơn nữa, chúng ta có thể giải thích rằng:

  • A Party is reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber is used by one-to-many Parties

Đó là lý do tại sao tôi đã thêm PartyPhoneNumberthực thể mô tả liên kết nhiều-nhiều có hiệu lực giữa các loại thực thể PartyPhoneNumberloại.

Đảng và Câu lạc bộ hoặc Người

Sau đó, nó cũng có thể được đọc rằng:

  • A Party is either a Club or a Person

Do đó, Partycung cấp một kết nối từ một trong hai Clubs hoặc People đến Addresses(hoặc PhoneNumbers).

Người là thành viên của nhiều câu lạc bộ

Như @aldwinaldwin đã đề cập trong câu trả lời của mình, nếu bạn muốn cung cấp chức năng cho một người trở thành thành viên của nhiều câu lạc bộ , thì bạn có thể bao gồm một bảng được gọi ClubMemberlà hoạt động tương tự nhiều người khác, lần này, một cách tự nhiên , kết nối PersonClub.

Tôi sẽ thêm vào ở trên rằng bảng này cũng có thể hữu ích trong mục tiêu lưu trữ bất kỳ người cụ thể nàochủ sở hữu của nhiều câu lạc bộ , bằng cách đưa vào IsClubOwnercột boolean đã đề cập . Trong thực tế, người ta có thể nói rằng bảng mới này là đại diện của một loại thực thể tách rời theo đúng nghĩa của nó.

Như được minh họa trong Hình 3 , bảng như vậy yêu cầu PK tổng hợp được tạo thành từ các cột ClubIdMemberId( tên vai trò [3] được đặt cho PersonId) và các cột này cũng phải được định nghĩa là FK trỏ, tương ứng, ClubPerson.

Hình 3. Mô hình dữ liệu câu lạc bộ và thành viên - Người là thành viên của nhiều câu lạc bộ

Một cấu trúc dễ thích nghi hơn

Sử dụng cài đặt này, bạn cũng có thể tuân thủ quy tắc ban đầu nói rằng a Person can be a member of only one Club, nhưng bạn chỉ cần thêm một CONSTRAINT ĐỘC ĐÁO vào MemberIdcột, để có thể nhập một giá trị nhất định không quá một lần. Vì vậy, như bạn có thể lưu ý, cấu trúc này có khả năng thích ứng cao hơn nhiều so với cấu trúc được hiển thị trong Hình 1 , vì bằng cách thả UNIQUE CONSTRAINT (hoặc INDEX), bạn sẽ mở chức năng nói trên về việc cho phép một người trở thành thành viên của các câu lạc bộ khác nhau tại cùng một lúc

Thành viên và chủ sở hữu dưới dạng các loại thực thể riêng biệt

Như bạn đã biết, việc lưu trữ một số sự thật về vai trò được thực hiện bởi một người với tư cách là chủ sở hữu của một câu lạc bộ chính vì sự tồn tại đơn thuần của nó trong một thuộc tính đúng hoặc sai có thể rất thuận lợi. Ví dụ, bạn có thể muốn giữ ngày hiệu lực trong đó một người xác định trở thành chủ sở hữu của một câu lạc bộ , do đó bạn có thể quản lý tình huống này bằng cách giới thiệu một loại thực thể riêng biệt được gọi ClubOwner, như được trình bày trong Hình 4 .

Hình 4. Mô hình dữ liệu câu lạc bộ và thành viên - Thành viên và chủ sở hữu dưới dạng các thực thể riêng biệt

Khi bạn xây dựng bảng dựa trên loại thực thể mới này, bạn có thể thêm các cột phù hợp đại diện cho các đặc điểm chỉ phát huy khi a PersonOwnercủa a Club. Như mô tả, bảng này sẽ chứa một PK bao gồm các cột FK tham chiếu Person.PersonIdClub.ClubId, theo cách này, bất kỳ sự kết hợp nào của ClubOwner.OwnerId(hoặc ClubOwner.PersonId, nếu bạn muốn) và ClubOwner.ClubIdcó thể được chèn chỉ trong một cơ hội.

Tất nhiên, với cấu hình này, bạn vẫn có thể xuất phát ở dạng boolean nếu a PersonOwnermột đặc biệt Clubvới sự trợ giúp của truy vấn trả về giá trị vô hướng có thể được đánh giá là đúng hoặc sai .


Ghi chú

1. Định nghĩa tích hợp cho mô hình hóa thông tin ( IDEF1X ) là một kỹ thuật mô hình hóa dữ liệu rất được khuyến khích , được định nghĩa là một tiêu chuẩn vào tháng 12 năm 1993 bởi Viện Tiêu chuẩn và Công nghệ Quốc gia Hoa Kỳ ( NIST ). Nó được kiên cố dựa trên (a) một số các giấy tờ lý thuyết tác giả của người khởi của mô hình quan hệ , tức là, Tiến sĩ EF Codd ; trên (b) lý thuyết Mối quan hệ thực thể , được phát triển bởi Tiến sĩ PP Chen ; và cũng trên (c) Kỹ thuật thiết kế cơ sở dữ liệu logic , được tạo bởi Robert G. Brown . Điều đáng chú ý là IDEF1X làchính thức hóa bằng cách logic thứ nhất .

2. ALTERNATE KEY là một thuộc tính (hoặc kết hợp các thuộc tính) chứa các giá trị xác định duy nhất một thực thể nhưng không được chọn làm PK của loại thực thể thích hợp; mỗi loại thực thể có thể có 0, một hoặc nhiều phím ALTERNATE. Trong một mô hình IDEF1X, họ đang được chỉ định là “AK” cộng với số tương ứng của nó, ví dụ như, AK1, AK2, vv Họ thường được thực hiện trong một SQL DDL cấu trúc thông qua một UNIQUE CONSTRAINT (hoặc UNIQUE INDEX ).

3. Tên vai trò là các ký hiệu (hoặc bí danh) được gán cho các thuộc tính FK để thể hiện ý nghĩa mà chúng giữ trong phạm vi của thực thể tương ứng. Việc sử dụng chúng được khuyến nghị từ năm 1970 bởi Tiến sĩ Codd trong bài báo chuyên đề của ông có tên là Mô hình dữ liệu quan hệ cho các ngân hàng dữ liệu chia sẻ lớn . Về phần mình, tính trung thực của IDEF1X về việc giữ liên quan đến các hoạt động quan hệ , Wap cũng ủng hộ việc đặt tên.


2
  1. Nếu một chủ sở hữu luôn là một thành viên của câu lạc bộ của mình. Thêm chủ sở hữu vào bảng Câu lạc bộ và đặt personId vào đó của thành viên là chủ sở hữu.
  2. Tự động đăng ký Id là tốt. Bạn có thể thêm một trường 'mã' khác, ở đó bạn đặt mã thành viên vào thẻ câu lạc bộ ở đó.
  3. Nên tự động ok (tôi nghĩ)
  4. Đặt personId vào số điện thoại và bảng email.

... Bạn không thể là thành viên của nhiều câu lạc bộ? Nếu bạn có thể, hãy tạo một bảng ClubMember với clubId và personId. Bằng cách đó bạn có thể kết nối một người với nhiều câu lạc bộ.


1
Nếu tôi muốn câu lạc bộ của mình có số điện thoại thì sao? Tôi có đặt clubIdphonenumber không và rời khỏi câu lạc bộ hoặc người được đặt thành null?
Vahx

Tôi sẽ không tách biệt tất cả các đối tượng (chuẩn hóa dữ liệu). Chỉ cần đặt 1 số điện thoại trong bảng câu lạc bộ. Bình thường hóa là tốt, nhưng quá nhiều bình thường hóa có thể gây ra vấn đề.
aldwinaldwin

1
Nhưng giả sử tôi muốn làm điều này? Tôi sẽ lấy địa chỉ làm ví dụ, thành viên có địa chỉ nhưng các câu lạc bộ cũng sẽ cần một địa chỉ
Vahx

1
Tạo một bản ghi địa chỉ và đặt địa chỉId trong câu lạc bộ. Bởi vì một câu lạc bộ có 1 địa chỉ, một thành viên có 1 địa chỉ. Đối với số điện thoại, bạn cần đặt personId vào bản ghi âm của phonenumber để có 1 đến nhiều. ..... Bạn có thể tạo một bảng personPhoneNumber (personId, phonenumberId) + bảng clubPhoneNumber (clubId, phonenumberId) điều gì làm cho nó trở thành mối quan hệ nhiều hơn sau đó.
aldwinaldwin
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.