मेरा मानना है कि यह उन दुर्लभ मामलों में से एक है जहां प्राकृतिक चाबियों के बजाय सरोगेट कुंजियों (auto_increment id's) के उपयोग ने आपको भटका दिया है। विचार करें कि यदि आप इसके बजाय प्राकृतिक कुंजियों का उपयोग करते हैं तो आपकी तालिका परिभाषाएँ कैसी दिखाई देंगी:
CREATE TABLE showing
(
name VARCHAR(45) NOT NULL, -- globally unique
PRIMARY KEY (name)
)
CREATE TABLE reservation
(
showing_name VARCHAR(45) NOT NULL,
name VARCHAR(45) NOT NULL, -- only unique within showing_name
PRIMARY KEY (name, showing_name),
FOREIGN KEY (showing_name) REFERENCES showing(name)
)
CREATE TABLE reservation_seat
(
showing_name VARCHAR(45) NOT NULL,
reservation_name VARCHAR(45) NOT NULL,
seat_row VARCHAR(45) NOT NULL,
seat_column VARCHAR(45) NOT NULL,
confirmed TINYINT,
PRIMARY KEY (showing_name, reservation_name, seat_row, seat_column),
FOREIGN KEY (showing_name, reservation_name) REFERENCES reservation(showing_name, name),
FOREIGN KEY (seat_row, seat_column) REFERENCES seat(row, column)
)
अब आप आरक्षण_सीट पर एक वैकल्पिक कुंजी के रूप में बाधा दिखाने के लिए अपनी आरक्षित सीट जोड़ सकते हैं:
CREATE TABLE reservation_seat
(
showing_name VARCHAR(45) NOT NULL,
reservation_name VARCHAR(45) NOT NULL,
seat_row VARCHAR(45) NOT NULL,
seat_column VARCHAR(45) NOT NULL,
confirmed TINYINT,
PRIMARY KEY (showing_name, reservation_name, seat_row, seat_column),
FOREIGN KEY (showing_name, reservation_name) REFERENCES reservation(showing_name, name),
FOREIGN KEY (seat_row, seat_column) REFERENCES seat(row, column),
CONSTRAINT UC_seat_showing_reserved UNIQUE(showing_name, seat_row, seat_column)
)
हालांकि, इससे यह स्पष्ट हो जाता है कि प्राथमिक कुंजी अनावश्यक है क्योंकि यह हमारे द्वारा जोड़े गए प्रतिबंध का केवल एक कमजोर संस्करण है, इसलिए हमें इसे अपनी नई बाधा से बदलना चाहिए।
CREATE TABLE reservation_seat
(
showing_name VARCHAR(45) NOT NULL,
reservation_name VARCHAR(45) NOT NULL,
seat_row VARCHAR(45) NOT NULL,
seat_column VARCHAR(45) NOT NULL,
confirmed TINYINT,
PRIMARY KEY (showing_name, seat_row, seat_column),
FOREIGN KEY (showing_name, reservation_name) REFERENCES reservation(showing_name, name),
FOREIGN KEY (seat_row, seat_column) REFERENCES seat(row, column)
)
अब हमें चिंता हो सकती है कि हमारा रिजर्वेशन_सीट रिजर्वेशन_सीट से भिन्न शो_आईडी वाले रिजर्वेशन को संदर्भित कर सकता है, लेकिन यह नेचुरल कीज के लिए कोई समस्या नहीं है क्योंकि पहला फॉरेन की रेफरेंस इसे रोकता है।
अब हमें बस इतना करना है कि इसे वापस सरोगेट कुंजियों में बदलना है:
CREATE TABLE reservation_seat
(
id INT NOT NULL AUTO_INCREMENT,
showing_id INT NOT NULL,
reservation_id INT NOT NULL,
seat_id INT NOT NULL,
confirmed TINYINT,
PRIMARY KEY (id),
FOREIGN KEY (showing_id, reservation_id) REFERENCES reservation(showing_id, id),
FOREIGN KEY (seat_id) REFERENCES seat(id),
CONSTRAINT UC_seat_showing_reserved UNIQUE(showing_id, seat_id)
)
चूंकि हम रिजर्वेशन_सीट (आईडी) को प्राथमिक कुंजी बना रहे हैं, इसलिए हमें नामित पीके परिभाषा को एक अद्वितीय बाधा में बदलना होगा। आपकी मूल रिजर्वेशन_सीट परिभाषा की तुलना में, हमने शो_आईडी जोड़ा है, लेकिन संशोधित मजबूत पहली विदेशी कुंजी परिभाषा के साथ अब हम दोनों का बीमा करते हैं कि रिजर्वेशन_सीट एक शो के भीतर अद्वितीय है और आरक्षण_सीट में अपने मूल आरक्षण से अलग शोइंग_आईडी नहीं हो सकती है।
(नोट:आपको संभवतः उपरोक्त SQL कोड में 'पंक्ति' और 'कॉलम' कॉलम नामों को उद्धृत करना होगा)
अतिरिक्त नोट: डीबीएमएस इस पर भिन्न है (और मुझे इस मामले में MySQL के बारे में निश्चित नहीं है), लेकिन कई लोगों को यह आवश्यक होगा कि एक विदेशी कुंजी संबंध में लक्ष्य (संदर्भित) तालिका पर संबंधित प्राथमिक कुंजी या अद्वितीय बाधा हो। इसका मतलब यह होगा कि आपको आरक्षण में बदलाव करना होगा एक नई बाधा के साथ तालिका:
CONSTRAINT UC_showing_reserved UNIQUE(showing_id, id)
आरक्षण_सीट . पर नई FK परिभाषा से मेल खाने के लिए जो मैंने ऊपर सुझाया था:
FOREIGN KEY (showing_id, reservation_id) REFERENCES reservation(showing_id, id),
तकनीकी रूप से, यह एक अनावश्यक बाधा होगी क्योंकि यह आरक्षण तालिका पर प्राथमिक कुंजी का कमजोर संस्करण है, लेकिन इस मामले में एसक्यूएल को शायद अभी भी एफके को लागू करने की आवश्यकता होगी।