Sunar özellikleri olarak bilinen konuyla ilgili -ki senaryoyu analiz zamansal veri tabanları - kavramsal açısından bakıldığında, bir tespit edilebilir: (a) bir “mevcut” Öyküsü Version Blog ve (b), bir “son” Blog Öyküsü şekli , çok rağmen benzeyen, farklı tipte varlıklardır.
Buna ek olarak, mantıksal soyutlama düzeyinde çalışırken, farklı türlerin gerçekleri (satırlarla temsil edilir) farklı tablolarda tutulmalıdır. Söz konusu durumda, oldukça benzer olsa bile, (i) “mevcut” Sürümler hakkındaki gerçekler (ii) “Geçmiş” Sürümler hakkındaki gerçeklerden farklıdır .
Bu nedenle durumu iki tablo aracılığıyla yönetmenizi öneririm:
her biri (1) biraz farklı sütunlara ve (2) farklı bir kısıtlama grubuna sahiptir.
Kavramsal katmana geri dönersek - iş ortamınızda - Yazar ve Editör'ün , bir Kullanıcı tarafından oynanabilecek Roller olarak tanımlanabilecek kavramlar olduğunu ve bu önemli yönlerin veri türüne (mantıksal düzey manipülasyon işlemleri yoluyla) bağlı olduğunu düşünüyorum. ve yorumlama ( bir veya daha fazla uygulama programının yardımı ile Blog Hikayeleri okuyucuları ve yazarları tarafından bilgisayarlı bilgi sisteminin dış seviyesinde gerçekleştirilir).
Tüm bu faktörleri ve diğer ilgili noktaları aşağıdaki gibi detaylandıracağım.
İş kuralları
Gereksinimlerinizi anladığım kadar, aşağıdaki iş kuralları formülasyonları (ilgili varlık türleri ve bunların karşılıklı ilişki türleri açısından bir araya getirilir), ilgili kavramsal şemanın oluşturulmasında özellikle yardımcı olur :
- Bir Kullanıcı sıfır bir veya birden fazla Blog Yazısı yazar
- Bir BlogStory sıfır veya bir veya daha fazla BlogStoryVersions tutar
- Bir Kullanıcı sıfır bir veya birçok BlogStoryVersions yazdı
Açıklayıcı IDEF1X diyagramı
Sonuç olarak, bir grafik aleti ile benim öneri açıklamak amacıyla, bir örnek IDEF1X oluşturduk bir ilgili gibi iş üzerinde formüle kuralları ve diğer özellikler elde edilir diyagramıdır. Şekil 1'de gösterilmiştir :
BlogStory ve BlogStoryVersion neden iki farklı varlık türü olarak kavramsallaştırılıyor?
Çünkü:
Bir BlogStoryVersion örneği (yani, “geçmiş” bir örnek) her zaman UpdatedDateTime özelliği için bir değer tutarken, BlogStory oluşumu (yani, “mevcut” bir örnek) hiçbir zaman bunu tutmaz .
Ayrıca, bu türlerin varlıkları iki farklı özellik kümesinin değerleri ile benzersiz olarak tanımlanır: BlogStoryNumber ( BlogStory olayları durumunda ) ve BlogStoryNumber artı CreatedDateTime ( BlogStoryVersion örnekleri durumunda ).
a Bilgi Modelleme için Entegrasyon Tanımı ( IDEF1X ),Aralık 1993'te Amerika Birleşik Devletleri Ulusal Standartlar ve Teknoloji Enstitüsü (NIST)tarafından standart olarak oluşturulmuş, oldukça tavsiye edilen bir veri modelleme tekniğidir. Erken teorik malzemeye dayanmaktadır tarafından kaleme yegane yaratıcısı ait ilişkisel modeli yani, Dr EF Codd ; üzerinde Varlık-İlişki tarafından geliştirilen veriler, görüş Dr. PP Chen ; ve ayrıca Robert G. Brown tarafından oluşturulan Mantıksal Veritabanı Tasarım Tekniği.
Açıklayıcı mantıksal SQL-DDL düzeni
Daha sonra, daha önce sunulan kavramsal analize dayanarak, aşağıdaki mantıksal seviyedeki tasarımı beyan ettim:
-- 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.
);
MySQL 5.6 üzerinde çalışan bu SQL Fiddle'da test edilmiştir .
BlogStory
tablo
Demo tasarımında da görebileceğiniz gibi BlogStory
, INT veri tipiyle PRIMARY KEY (kısaltma için PK) sütununu tanımladım . Bu bağlamda, her satır eklemesinde böyle bir sütun için sayısal bir değer üreten ve atayan yerleşik bir otomatik işlemi düzeltmek isteyebilirsiniz. Bu değer kümesinde zaman zaman boşluk bırakmayı düşünmezseniz , MySQL ortamlarında yaygın olarak kullanılan AUTO_INCREMENT özniteliğini kullanabilirsiniz .
Tüm bireysel BlogStory.CreatedDateTime
veri noktalarınızı girerken , veritabanı sunucusunda geçerli olan Tarih ve Saat değerlerini tam INSERT işlem anında döndüren NOW () işlevini kullanabilirsiniz . Bana göre, bu uygulama kesinlikle harici rutinlerin kullanımından daha uygun ve hatalara daha az eğilimlidir.
(Artık kaldırılmış) yorumlarda tartışıldığı gibi, BlogStory.Title
yinelenen değerleri koruma olasılığından kaçınmak istemeniz koşuluyla, bu sütun için bir UNIQUE kısıtlaması ayarlamanız gerekir . Bir arama sonuçları gerçeğine Başlık birkaç (hatta tüm) “Geçtiğimiz” tarafından paylaşılabilir BlogStoryVersions ardından bir UNIQUE gerekir değil için kurulacak BlogStoryVersion.Title
sütununda.
I dahil BlogStory.IsActive
tipi kolon BIT (1) , (a-se Tinyint Eğer “yumuşak” ya da “mantıklı” SİL işlevselliği sağlamak için ihtiyaç halinde de kullanılabilir).
BlogStoryVersion
Tablo hakkında detaylar
Öte yandan, BlogStoryVersion
tablonun PK'si, (a) BlogStoryNumber
ve (b) adında bir sütundan oluşur CreatedDateTime
, elbette, bir BlogStory
satırın bir INSERT geçirdiği kesin anı işaretler .
BlogStoryVersion.BlogStoryNumber
, PK'nın bir parçası olmasının yanı sıra, bu iki tablonun satırları arasında referans bütünlüğünüBlogStory.BlogStoryNumber
zorunlu kılan bir yapılandırma olan , referans veren bir YABANCI ANAHTAR (FK) olarak kısıtlanır . Bu bağlamda, otomatik bir a neslinin uygulanması gerekli değildir, çünkü FK olarak ayarlandığında, bu sütuna EKLENEN değerler ilgili muadilinde zaten bulunanlardan “alınmalıdır” .BlogStoryVersion.BlogStoryNumber
BlogStory.BlogStoryNumber
BlogStoryVersion.UpdatedDateTime
Kolon, beklendiği gibi, muhafaza etmelidir, bir zaman noktası BlogStory
satır ilave bir sonucu olarak, modifiye edilmiş ve BlogStoryVersion
tablo. Bu nedenle, bu durumda NOW () işlevini de kullanabilirsiniz.
Aralıklı arasında kavramış BlogStoryVersion.CreatedDateTime
ve BlogStoryVersion.UpdatedDateTime
tüm ifade Dönemi bir süre boyunca BlogStory
satır “mevcut” veya “geçerli” oldu.
Bir Version
sütun için dikkat edilmesi gerekenler
Bir BlogStory'ninBlogStoryVersion.CreatedDateTime
belirli bir “geçmiş” Sürümünü temsil eden değeri tutan sütun olarak düşünmek yararlı olabilir . Bunu bir veya çok daha faydalı görüyorum , çünkü insanların zaman kavramlarına daha aşina olmaları açısından kullanıcı dostudur. Örneğin, blog yazarları veya okuyucular bir BlogStoryVersion'a aşağıdakine benzer bir şekilde başvurabilir :VersionId
VersionCode
- “Ben özgü görmek istiyorum Versiyon ait BlogStory tarafından tespit Number
1750
edildi düzenlendi üzerine 26 August 2015
de 9:30
”.
Yazar ve Editör Roller: Veri türetme ve yorumlanması
Bu yaklaşımla, kolayca “orijinal” kimin elinde olduğunu ayırt edebilir AuthorId
bir betonun BlogStory “en erken” seçerek Sürüm belli bir BlogStoryId
GELEN BlogStoryVersion
uygulayarak sayesinde masanın MİN () fonksiyonu için BlogStoryVersion.CreatedDateTime
.
Bu şekilde, tüm "daha sonraki" veya "başarılı" Sürüm satırlarında BlogStoryVersion.AuthorId
bulunan her değer , doğal olarak, eldeki ilgili Sürümün Yazar tanımlayıcısını gösterir , ancak böyle bir değerin aynı zamanda, Rol dahil oynadığı Kullanıcı olarak Editor “orijinal” nin Version a BlogStory .
Evet, belirli bir AuthorId
değer birden çok BlogStoryVersion
satır tarafından paylaşılabilir , ancak bu aslında her Sürüm için çok önemli bir şey söyleyen bir bilgi parçasıdır , bu nedenle söz konusu verilerin tekrarlanması bir sorun değildir .
DATETIME sütunlarının biçimi
DATETIME veri türüne gelince, evet, haklısınız, “ MySQL, DATETIME değerlerini ' YYYY-MM-DD HH:MM:SS
' biçiminde alır ve görüntüler ”, ancak ilgili verileri güvenle bu şekilde girebilirsiniz ve bir sorgu gerçekleştirmeniz gerektiğinde diğer şeylerin yanı sıra, ilgili değerleri kullanıcılarınız için uygun biçimde göstermek için yerleşik DATE ve TIME işlevlerinden yararlanın. Ya da kesinlikle bu tür veri biçimlendirmelerini uygulama program (lar) ınız koduyla yapabilirsiniz.
Etkileri BlogStory
GÜNCELLEME operasyonları
Her BlogStory
satırda bir GÜNCELLEME olduğunda , değişiklik yapılana kadar “mevcut” karşılık gelen değerlerin BlogStoryVersion
tabloya eklenmesini sağlamalısınız . Bu nedenle, bölünmez bir İş Birimi olarak muamele görmelerini garanti etmek için bu operasyonları tek bir ASİT İŞLEMİ içinde gerçekleştirmenizi şiddetle tavsiye ederim . TRIGGERS'ı da kullanabilirsiniz, ancak tabiri caizse, işleri düzensiz yapma eğilimindedirler.
Bir VersionId
veya VersionCode
sütuna giriş
BlogStoryVersions'ı ayırt etmek için (iş koşulları veya kişisel tercih nedeniyle) bir BlogStory.VersionId
veya BlogStory.VersionCode
sütun eklemeyi seçerseniz , aşağıdaki olasılıkları düşünmeniz gerekir:
A'nın VersionCode
(i) tüm BlogStory
tabloda ve ayrıca (ii) 'de EŞSİZ olması gerekebilir BlogStoryVersion
.
Bu nedenle, her bir değeri oluşturmak ve atamak için dikkatle test edilmiş ve tamamen güvenilir bir yöntem uygulamanız gerekir Code
.
Belki, VersionCode
değerler farklı BlogStory
satırlarda tekrarlanabilir , ancak asla aynı ile tekrarlanamaz BlogStoryNumber
. Örneğin:
- bir BlogStoryNumber
3
- Sürüm83o7c5c
ve aynı anda
- Bir BlogStoryNumber
86
- Sürüm83o7c5c
ve
- Bir BlogStoryNumber
958
- Sürüm83o7c5c
.
Daha sonraki olasılık başka bir alternatif açar:
Bir tutulması VersionNumber
için BlogStories
, bu yüzden söz konusu olabilir:
- BlogStoryNumber
23
- Sürümler1, 2, 3…
;
- BlogStoryNumber
650
- Sürümler1, 2, 3…
;
- BlogStoryNumber
2254
- Sürümler1, 2, 3…
;
- vb.
“Orijinal” ve “sonraki” sürümleri tek bir tabloda tutma
Tüm muhafaza, ancak BlogStoryVersions olarak aynı ayrı temel tablo mümkündür, böylece istenmeyen yan etkileri vardır gerçekler, iki farklı (kavramsal) türleri karıştırma olacaktır, çünkü bunu yapmak için tavsiye
- veri kısıtlamaları ve manipülasyonu (mantıksal düzeyde) ile birlikte
- ilgili işleme ve depolama (fiziksel katmanda).
Ancak, bu hareket tarzını izlemeyi seçmeniz durumunda, yukarıda ayrıntılı olarak verilen fikirlerin çoğundan yararlanabilirsiniz, örneğin:
- bir INT sütunu ( ) ve bir DATETIME sütunu ( ) içeren bir bileşik PK ;
BlogStoryNumber
CreatedDateTime
- ilgili işlemleri optimize etmek için sunucu işlevlerinin kullanımı ve
- Yazar ve Editör türetilebilir Rolleri .
Böyle bir yaklaşıma devam ederek, "daha yeni" Sürümler eklenir eklenmez bir BlogStoryNumber
değerin çoğaltılacağını görerek, değerlendirebileceğiniz ve (önceki bölümde bahsedilenlere çok benzer) bir seçenek PK oluşturuyor sütunlardan oluşur ve bu şekilde bir BlogStory'nin her bir Sürümünü benzersiz bir şekilde tanımlayabilirsiniz . Ve bir kombinasyonu ile deneyebilir ve çok.BlogStory
BlogStoryNumber
VersionCode
BlogStoryNumber
VersionNumber
Benzer senaryo
Bu yardım sorusuna cevabımı bulabilirsiniz , çünkü ilgili veritabanındaki geçici yeteneklerin karşılaştırılabilir bir senaryo ile başa çıkmasını öneriyorum .