2011-05-20 13 views
9

मुझे डेटाबेस बनाना है और यह सुनिश्चित करना है कि हम डेटा को एक विशिष्ट तिथि पर लोड कर सकें, इसलिए मैंने tuple versioning का उपयोग करने का निर्णय लिया।ट्यूपल संस्करण और समग्र प्राथमिक कुंजी

मान लीजिए कि हम निम्न दो तालिकाओं करते हैं:

CREATE TABLE Author 
(
    Id UNIQUEIDENTIFIER NOT NULL, 
    Firstname VARCHAR(100) NOT NULL, 
    Surname VARCHAR(200) NOT NULL, 
    ValidFrom DATETIME NOT NULL, 
    ValidUntil DATETIME NULL, 
    PRIMARY KEY (ID, ValidFrom) 
) 

CREATE TABLE Book 
(
    Id UNIQUEIDENTIFIER NOT NULL, 
    Title VARCHAR(100) NOT NULL, 
    ISBN VARCHAR(100) NOT NULL, 
    AuthorId UNIQUEIDENTIFIER NOT NULL, 
    ValidFrom DATETIME NOT NULL, 
    ValidUntil DATETIME NULL, 
    PRIMARY KEY (Id, ValidFrom) 
) 

पहली बार जब मैं एक नए लेखक मैं एक नया GUID उत्पन्न होगा दर्ज करें। मैं पुस्तक तालिका में इस GUID का उपयोग करने के साथ-साथ लेखक का संदर्भ भी देता हूं।

यदि लेखक पर कोई अपडेट है, तो मैं एक ही GUID के साथ एक नया रिकॉर्ड बनाता हूं, लेकिन वर्तमान दिनांक को "ValidFrom" के रूप में परिभाषित करता हूं और मूल रिकॉर्ड से "ValidUntil" को वर्तमान दिनांक तक भी सेट करता हूं।

मुझे पुस्तक तालिका को बदलने की ज़रूरत नहीं है क्योंकि लेखक.आईडी नहीं बदला।

समस्या मैं अब का सामना करना पड़ रहा हूँ

कि मैं Book.AuthorId = Author.Id

पर एक विदेशी कुंजी बाधा जोड़ने के लिए दुर्भाग्य से यह काम नहीं करता, क्योंकि मैं एक समग्र प्राथमिक कुंजी का उपयोग करें चाहते हैं। मैं अपनी पुस्तक तालिका में लेखक। ValidFrom को जोड़ना नहीं चाहता क्योंकि मैं बस हालिया एक को संदर्भित करना चाहता हूं, न कि एक विशिष्ट संस्करण।

इस पर कोई विचार है कि मैं इसे कैसे हल कर सकता हूं? मुझे लगता है कि मैं एक ट्रिगर जोड़ सकता हूं जो सुनिश्चित करता है कि अगर कोई किताब पहले से दर्ज की गई है तो आप एक लेखक को हटा नहीं सकते हैं, लेकिन मेरे पास कैस्केड हटाने की अनुमति देने का कोई समाधान नहीं है।

मैं हर संकेत या सलाह के लिए आभारी हूं।

+1

+1 को टुपल संस्करण –

+1

का उल्लेख करने के लिए हटा रहे हैं कम से कम SQL सर्वर 2008? मेगन फॉक्स के संबंध में डेटाबेस डिजाइन को –

+2

+1। – Yuck

उत्तर

3

यह 2008 पर काम करता है (एक पंक्ति का उपयोग करके निर्भर करता है कि किस पंक्ति को परमाणु रूप से संदर्भित किया जा रहा है)। यह नए कॉलम परिचय करता है, तो आप उन्हें एक दृश्य के पीछे छिपाने के लिए चाहते हो सकता है:

CREATE TABLE Author 
(
    Id UNIQUEIDENTIFIER NOT NULL, 
    Firstname VARCHAR(100) NOT NULL, 
    Surname VARCHAR(200) NOT NULL, 
    ValidFrom DATETIME NOT NULL, 
    ValidUntil DATETIME NULL, 
    Active as CASE WHEN ValidUntil is null THEN CONVERT(datetime,'99991231',112) ELSE ValidUntil END Persisted 
    PRIMARY KEY (ID, ValidFrom), 
    UNIQUE (ID,Active) 
) 
go 
CREATE TABLE Book 
(
    Id UNIQUEIDENTIFIER NOT NULL, 
    Title VARCHAR(100) NOT NULL, 
    ISBN VARCHAR(100) NOT NULL, 
    AuthorId UNIQUEIDENTIFIER NOT NULL, 
    ValidFrom DATETIME NOT NULL, 
    ValidUntil DATETIME NULL, 
    PRIMARY KEY (Id, ValidFrom), 
    FK_Link as CONVERT(datetime,'99991231',112) persisted, 
    Foreign key (AuthorID,FK_Link) references Author (Id,Active) on delete cascade 
) 
go 
declare @AuthorId uniqueidentifier 
set @AuthorId = NEWID() 
insert into Author(Id,Firstname,Surname,ValidFrom) 
select @AuthorId,'Boris','McBoris',CURRENT_TIMESTAMP 
insert into Book(Id,Title,ISBN,AuthorId,ValidFrom) 
select NEWID(),'How to use tuple versioning','12345678',@AuthorId,CURRENT_TIMESTAMP 

;with newAuthorInfo as (
    select @AuthorId as Id,'Steve' as Firstname,'McBoris' as Surname,t.Dupl 
    from (select 0 union all select 1) t(Dupl) 
) 
merge into Author a 
using newAuthorInfo nai 
on 
    a.Id = nai.Id and 
    a.ValidUntil is null and 
    nai.Dupl = 0 
when matched then update set ValidUntil = CURRENT_TIMESTAMP 
when not matched then insert (Id,Firstname,Surname,ValidFrom) 
values (nai.Id,nai.Firstname,nai.Surname,CURRENT_TIMESTAMP); 

;with newAuthorInfo as (
    select @AuthorId as Id,'Steve' as Firstname,'Sampson' as Surname,t.Dupl 
    from (select 0 union all select 1) t(Dupl) 
) 
merge into Author a 
using newAuthorInfo nai 
on 
    a.Id = nai.Id and 
    a.ValidUntil is null and 
    nai.Dupl = 0 
when matched then update set ValidUntil = CURRENT_TIMESTAMP 
when not matched then insert (Id,Firstname,Surname,ValidFrom) 
values (nai.Id,nai.Firstname,nai.Surname,CURRENT_TIMESTAMP); 

go 
select * from Author 
select * from Book 

delete from Author where ValidUntil is not null 

select * from Author 
select * from Book 

delete from Author 

select * from Author 
select * from Book 

एक पूर्व -2008 समाधान के लिए, मुझे नहीं लगता कि आप ट्रिगर से बेहतर कर सकते हैं। आप एक दूसरी लेखक तालिका पेश कर सकते हैं जिसमें केवल आईडी कॉलम (विशिष्ट रूप से) है, जिसे आप पुस्तक से एफके कर सकते हैं, और कैस्केड उस तालिका से पुस्तक में हटा सकते हैं। फिर आपको लेखक पर एक डिलीट ट्रिगर की आवश्यकता है, जैसे कि यदि आप किसी विशेष लेखक आईडी के लिए लेखक से अंतिम पंक्ति को हटा रहे हैं, तो आप इस नई तालिका

+0

आपके सुझाव के लिए धन्यवाद, लेकिन मुझे लगता है कि यह SQL Server 2008 के साथ भी काम नहीं करेगा क्योंकि लेखक (आईडी, एक्टिव) पर अद्वितीय कन्स्ट्रेंट केवल तभी काम करता है जब हमारे पास रिकॉर्ड के एक या दो संस्करण हों।तीसरे अपडेट के साथ, हमारे पास दो निष्क्रिय और एक सक्रिय रिकॉर्ड हैं। – MFox

+0

@MFox - मैंने इसे ठीक कर दिया है (और एक तीसरी नमूना पंक्ति जोड़ा) तो यह 2008 में काम करता है। मुझे 2005 के समाधान पर विचार करना होगा। –

संबंधित मुद्दे