Phân tích kịch bản -which quà đặc điểm gắn liền với chủ đề được gọi là cơ sở dữ liệu theo thời gian - từ góc độ lý thuyết, người ta có thể xác định rằng: (a) “có mặt” Blog Câu chuyện bản và (b) một “quá khứ” Blog Câu chuyện bản , mặc dù rất tương tự, là các thực thể của các loại khác nhau.
Ngoài ra, khi làm việc ở mức độ trừu tượng logic, các sự kiện (được biểu thị bằng các hàng) của các loại riêng biệt phải được giữ lại trong các bảng riêng biệt. Trong trường hợp đang được xem xét, ngay cả khi khá giống nhau, (i) các sự kiện về Phiên bản hiện tại của Khác biệt với (ii) sự thật về Phiên bản trước đây của Phiên bản .
Do đó tôi khuyên bạn nên quản lý tình huống bằng hai bảng:
một phiên bản dành riêng cho các phiên bản hiện tại và các phiên bản hiện tại của Wikipedia và
một trong đó là riêng biệt, mà còn liên kết với người khác, cho tất cả các hoặc “quá khứ” “trước” phiên bản ;
mỗi cột có (1) một số cột hơi khác biệt và (2) một nhóm các ràng buộc khác nhau.
Quay lại lớp khái niệm, Tôi cho rằng -in kinh doanh với môi trường của bạn Tác giả và biên tập viên là khái niệm có thể được mô tả như vai trò có thể được chơi bởi một tài khoản , và những khía cạnh quan trọng phụ thuộc vào dữ liệu nguồn gốc (thông qua các hoạt động thao tác logic cấp) và giải thích (được thực hiện bởi các độc giả và nhà văn Blog Stories , ở cấp độ bên ngoài của hệ thống thông tin máy tính, với sự hỗ trợ của một hoặc nhiều chương trình ứng dụng).
Tôi sẽ chi tiết tất cả các yếu tố này và các điểm liên quan khác như sau.
Quy tắc kinh doanh
Theo hiểu biết của tôi về các yêu cầu của bạn, các công thức quy tắc kinh doanh sau đây (được kết hợp theo các loại thực thể có liên quan và các loại mối quan hệ của chúng) đặc biệt hữu ích trong việc thiết lập lược đồ khái niệm tương ứng :
- Một người dùng viết không có một hoặc nhiều BlogStories
- Một BlogStory giữ zero-một-hoặc-nhiều BlogStoryVersions
- Một người dùng đã viết không một hoặc nhiều BlogStoryVersions
Sơ đồ IDEF1X tiếp xúc
Do đó, để thể hiện sự gợi ý của tôi nhờ thiết bị đồ họa, tôi đã tạo ra một IDEF1X mẫu, một sơ đồ bắt nguồn từ các quy tắc kinh doanh được xây dựng ở trên và các tính năng khác có vẻ phù hợp. Nó được hiển thị trong Hình 1 :
Tại sao BlogStory và BlogStoryVersion được khái niệm hóa thành hai loại thực thể khác nhau?
Bởi vì:
Một phiên bản BlogStoryVersion (ví dụ, một quá khứ trước đây) luôn giữ một giá trị cho một thuộc tính UpdateDateTime , trong khi sự xuất hiện của BlogStory (tức là một hiện tại của một ngôi sao) không bao giờ giữ nó.
Bên cạnh đó, các đơn vị của những loại được xác định duy nhất bởi các giá trị của hai bộ riêng biệt của thuộc tính: BlogStoryNumber (trong trường hợp của BlogStory lần xuất hiện), và BlogStoryNumber cộng CreatedDateTime (trong trường hợp của BlogStoryVersion trường hợp).
một Integration Definition Thông tin Modeling ( IDEF1X ) là một dữ liệu cao recommendable mô hình kỹ thuật mà đã được thành lập như là một tiêu chuẩn trong tháng 12 năm 1993 của Hoa Kỳ Viện Tiêu chuẩn và Công nghệ (NIST). Nó dựa trên các tài liệu lý thuyết ban đầu được tác giả bởi người khởi tạo duy nhất của mô hình quan hệ , tức là Tiến sĩ EF Codd ; trên quan điểm Thực thể-Mối quan hệ của dữ liệu, được phát triển bởi Tiến sĩ PP Chen ; và cũng trên Kỹ thuật thiết kế cơ sở dữ liệu logic, được tạo bởi Robert G. Brown.
Bố cục SQL-DDL logic minh họa
Sau đó, dựa trên phân tích khái niệm được trình bày trước đây, tôi đã tuyên bố thiết kế mức logic dưới đây:
-- You should determine which are the most fitting
-- data types and sizes for all your table columns
-- depending on your business context characteristics.
-- Also you should make accurate tests to define the most
-- convenient index strategies at the physical level.
-- As one would expect, you are free to make use of
-- your preferred (or required) naming conventions.
CREATE TABLE UserProfile (
UserId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
BirthDate DATETIME NOT NULL,
GenderCode CHAR(3) NOT NULL,
UserName CHAR(20) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
FirstName,
LastName,
BirthDate,
GenderCode
),
CONSTRAINT UserProfile_AK2 UNIQUE (UserName) -- ALTERNATE KEY.
);
CREATE TABLE BlogStory (
BlogStoryNumber INT NOT NULL,
Title CHAR(60) NOT NULL,
Content TEXT NOT NULL,
CoverImageName CHAR(30) NOT NULL,
IsActive BIT(1) NOT NULL,
AuthorId INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT BlogStory_PK PRIMARY KEY (BlogStoryNumber),
CONSTRAINT BlogStory_AK UNIQUE (Title), -- ALTERNATE KEY.
CONSTRAINT BlogStoryToUserProfile_FK FOREIGN KEY (AuthorId)
REFERENCES UserProfile (UserId)
);
CREATE TABLE BlogStoryVersion (
BlogStoryNumber INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
Title CHAR(60) NOT NULL,
Content TEXT NOT NULL,
CoverImageName CHAR(30) NOT NULL,
IsActive BIT(1) NOT NULL,
AuthorId INT NOT NULL,
UpdatedDateTime DATETIME NOT NULL,
--
CONSTRAINT BlogStoryVersion_PK PRIMARY KEY (BlogStoryNumber, CreatedDateTime), -- Composite PK.
CONSTRAINT BlogStoryVersionToBlogStory_FK FOREIGN KEY (BlogStoryNumber)
REFERENCES BlogStory (BlogStoryNumber),
CONSTRAINT BlogStoryVersionToUserProfile_FK FOREIGN KEY (AuthorId)
REFERENCES UserProfile (UserId),
CONSTRAINT DatesSuccession_CK CHECK (UpdatedDateTime > CreatedDateTime) --Let us hope that MySQL will finally enforce CHECK constraints in a near future version.
);
Đã thử nghiệm trong SQL Fiddle này chạy trên MySQL 5.6.
Cái BlogStory
bàn
Như bạn có thể thấy trong thiết kế demo, tôi đã định nghĩa cột BlogStory
PRIMARY KEY (PK for brevity) với kiểu dữ liệu INT. Về vấn đề này, bạn có thể muốn sửa một quy trình tự động tích hợp để tạo và gán một giá trị số cho một cột như vậy trong mỗi lần chèn hàng. Nếu thỉnh thoảng bạn không để lại các khoảng trống trong bộ giá trị này, thì bạn có thể sử dụng thuộc tính AUTO_INCREMENT , thường được sử dụng trong môi trường MySQL.
Khi nhập tất cả các BlogStory.CreatedDateTime
điểm dữ liệu riêng lẻ của bạn , bạn có thể sử dụng hàm NOW () , trả về các giá trị Ngày và Giờ hiện tại trong máy chủ cơ sở dữ liệu tại thời điểm thao tác INSERT chính xác. Đối với tôi, cách làm này được quyết định là phù hợp hơn và ít bị lỗi hơn so với việc sử dụng các thói quen bên ngoài.
Với điều kiện, như đã thảo luận trong các bình luận (hiện đã bị xóa), bạn muốn tránh khả năng duy trì BlogStory.Title
các giá trị trùng lặp, bạn phải thiết lập một ràng buộc ĐỘC ĐÁO cho cột này. Do thực tế là một Tiêu đề nhất định có thể được chia sẻ bởi một số (hoặc thậm chí là tất cả) trong quá khứ BlogStoryVersions , nên không nên thiết lập một ràng buộc KHÔNG GIỚI HẠN cho BlogStoryVersion.Title
cột.
Tôi đã bao gồm BlogStory.IsActive
cột loại BIT (1) (mặc dù TINYINT cũng có thể được sử dụng) trong trường hợp bạn cần cung cấp chức năng DEL mềm mềm hoặc hoặc logic logic DEL DEL.
Chi tiết về BlogStoryVersion
bảng
Mặt khác, PK của BlogStoryVersion
bảng bao gồm (a) BlogStoryNumber
và (b) một cột có tên CreatedDateTime
, tất nhiên, đánh dấu thời điểm chính xác trong đó một BlogStory
hàng trải qua một CHỨNG MINH.
BlogStoryVersion.BlogStoryNumber
, ngoài việc là một phần của PK, còn bị ràng buộc như là một NGOẠI TỆ (FK) tham chiếu BlogStory.BlogStoryNumber
, một cấu hình thực thi tính toàn vẹn tham chiếu giữa các hàng của hai bảng này. Về mặt này, việc thực hiện một thế hệ tự động của a BlogStoryVersion.BlogStoryNumber
là không cần thiết bởi vì, được đặt là FK, các giá trị được CHỈ vào cột này phải được rút ra từ các giá trị được đặt trong BlogStory.BlogStoryNumber
đối tác liên quan .
Các BlogStoryVersion.UpdatedDateTime
cột nên giữ lại, như mong đợi, điểm kịp thời khi một BlogStory
hàng đã được sửa đổi và, do đó, bổ sung vào BlogStoryVersion
bảng. Do đó, bạn cũng có thể sử dụng hàm NOW () trong tình huống này.
Các Interval thấu hiểu giữa BlogStoryVersion.CreatedDateTime
và BlogStoryVersion.UpdatedDateTime
thể hiện toàn bộ giai đoạn trong đó một BlogStory
hàng là “có mặt” hay “hiện tại”.
Cân nhắc cho một Version
cột
Có thể hữu ích khi nghĩ về BlogStoryVersion.CreatedDateTime
cột giữ giá trị đại diện cho một Phiên bản trước đây của một phiên bản cá nhân của BlogStory . Tôi cho rằng điều này có lợi hơn nhiều so với một VersionId
hoặc VersionCode
, vì nó thân thiện với người dùng hơn theo nghĩa mọi người có xu hướng quen thuộc hơn với các khái niệm thời gian . Chẳng hạn, các tác giả hoặc độc giả blog có thể tham khảo BlogStoryVersion theo cách tương tự như sau:
- Tôi muốn xem Phiên bản cụ thể của BlogStory được xác định bởi Số
1750
được tạo trên 26 August 2015
tại 9:30
.
Vai trò của tác giả và biên tập viên : Xuất phát và giải thích dữ liệu
Với cách tiếp cận này, bạn có thể dễ dàng phân biệt ai là người nắm giữ bản gốc AuthorId
của một BlogStory cụ thể LỰA CHỌN Phiên bản sớm nhất của một BlogStoryId
TỪ một BlogStoryVersion
bảng nhất định nhờ áp dụng hàm MIN () cho BlogStoryVersion.CreatedDateTime
.
Theo cách này, mỗi BlogStoryVersion.AuthorId
giá trị được chứa trong tất cả các hàng Phiên bản sau này hoặc các phiên bản thành công của các phiên bản , sau đó, chỉ ra, định danh Tác giả của Phiên bản tương ứng , nhưng người ta cũng có thể nói rằng giá trị đó đồng thời là biểu thị các vai trò chơi bởi tham gia tài như biên tập viên của “bản gốc” Version của một BlogStory .
Có, một AuthorId
giá trị nhất định có thể được chia sẻ bởi nhiều BlogStoryVersion
hàng, nhưng đây thực sự là một thông tin cho biết điều gì đó rất có ý nghĩa về mỗi Phiên bản , vì vậy việc lặp lại dữ liệu đã nói không phải là vấn đề.
Định dạng của các cột DATETIME
Đối với kiểu dữ liệu của DATETIME, vâng, bạn đã đúng, và MySQL truy xuất và hiển thị các giá trị của DATETIME theo YYYY-MM-DD HH:MM:SS
định dạng '' , nhưng bạn có thể tự tin nhập dữ liệu thích hợp theo cách này và khi bạn phải thực hiện một truy vấn bạn chỉ cần thực hiện sử dụng các hàm DATE và TIME tích hợp để, trong số những thứ khác, hiển thị các giá trị liên quan ở định dạng phù hợp cho người dùng của bạn. Hoặc bạn chắc chắn có thể thực hiện loại định dạng dữ liệu này thông qua mã chương trình ứng dụng của bạn.
Ý nghĩa của các BlogStory
hoạt động CẬP NHẬT
Mỗi khi một BlogStory
hàng bị CẬP NHẬT, bạn phải đảm bảo rằng các giá trị tương ứng là hiện tại của bản thân cho đến khi sửa đổi diễn ra sau đó được XÁC NHẬN vào BlogStoryVersion
bảng. Do đó, tôi đặc biệt khuyên bạn nên hoàn thành các hoạt động này trong một GIAO DỊCH ACID duy nhất để đảm bảo rằng chúng được coi là một Đơn vị công việc không thể chia cắt. Bạn cũng có thể sử dụng TRIGGERS, nhưng họ có xu hướng làm cho mọi thứ không gọn gàng, để nói.
Giới thiệu một VersionId
hoặc VersionCode
cột
Nếu bạn chọn (vì hoàn cảnh kinh doanh hoặc sở thích cá nhân) để kết hợp một BlogStory.VersionId
hoặc BlogStory.VersionCode
cột để phân biệt BlogStoryVersions , bạn nên suy nghĩ về các khả năng sau:
A VersionCode
có thể được yêu cầu là ĐỘC ĐÁO trong (i) toàn bộ BlogStory
bảng và cả trong (ii) BlogStoryVersion
.
Do đó, bạn phải thực hiện một phương pháp được kiểm tra cẩn thận và hoàn toàn đáng tin cậy để tạo và gán từng Code
giá trị.
Có thể, các VersionCode
giá trị có thể được lặp lại trong các BlogStory
hàng khác nhau , nhưng không bao giờ được nhân đôi cùng BlogStoryNumber
. Ví dụ: bạn có thể có:
- một BlogStoryNumber
3
- Phiên bản83o7c5c
và, đồng thời,
- một BlogStoryNumber
86
- Phiên bản83o7c5c
và
- một BlogStoryNumber
958
- Phiên bản83o7c5c
.
Khả năng sau này sẽ mở ra một phương án khác:
Giữ một VersionNumber
cho BlogStories
, vì vậy có thể có:
- BlogStoryNumber
23
- Phiên bản1, 2, 3…
;
- BlogStoryNumber
650
- Phiên bản1, 2, 3…
;
- BlogStoryNumber
2254
- Phiên bản1, 2, 3…
;
- Vân vân.
Tổ chức các phiên bản gốc và các phiên bản tiếp theo của Nhật Bản trong một bảng duy nhất
Mặc dù duy trì tất cả các BlogStoryVersions trong cùng một bảng cơ sở riêng lẻ , tôi khuyên bạn không nên làm điều đó bởi vì bạn sẽ trộn lẫn hai loại sự kiện (khái niệm) riêng biệt, do đó có tác dụng phụ không mong muốn đối với
- ràng buộc dữ liệu và thao tác (ở mức logic), cùng với
- việc xử lý và lưu trữ liên quan (ở tầng vật lý).
Nhưng, với điều kiện bạn chọn tuân theo tiến trình hành động đó, bạn vẫn có thể tận dụng nhiều ý tưởng chi tiết ở trên, ví dụ:
- một PK tổng hợp bao gồm một cột INT (
BlogStoryNumber
) và cột DATETIME ( CreatedDateTime
);
- việc sử dụng các chức năng của máy chủ để tối ưu hóa các quy trình thích hợp và
- các tác giả và biên tập viên derivable Roles .
Thấy rằng, bằng cách tiếp tục với cách tiếp cận như vậy, một BlogStoryNumber
giá trị sẽ được nhân đôi ngay sau khi thêm phiên bản mới hơn của Phiên bản , một tùy chọn mà bạn có thể đánh giá (rất giống với những gì được đề cập trong phần trước) đang thiết lập BlogStory
PK bao gồm các cột BlogStoryNumber
và VersionCode
, theo cách này, bạn sẽ có thể xác định duy nhất mỗi Phiên bản của BlogStory . Và bạn có thể thử với sự kết hợp BlogStoryNumber
và VersionNumber
quá.
Kịch bản tương tự
Bạn có thể tìm thấy câu trả lời của tôi cho câu hỏi trợ giúp này, vì tôi cũng đề xuất cho phép các khả năng tạm thời trong cơ sở dữ liệu liên quan để giải quyết một kịch bản có thể so sánh.