में या तो गैर-शून्य बाधाएं MySQL में गैर-नलिका बाधा उत्पन्न करने का सबसे अच्छा तरीका क्या है कि फ़ील्ड ए और फ़ील्डबी दोनों नल नहीं हो सकते हैं। मुझे कोई परवाह नहीं है कि कोई भी अपने आप से न्यूल है, बस जब तक कि अन्य क्षेत्र में गैर-शून्य मूल्य हो। और यदि दोनों के पास गैर-शून्य मान हैं, तो यह भी बेहतर है।MySQL
MySQL
उत्तर
MySQL 5.5 ने SIGNAL पेश किया, इसलिए हमें बिल करविन के उत्तर में अतिरिक्त कॉलम की आवश्यकता नहीं है। बिल ने बताया कि आपको अपडेट के लिए ट्रिगर की भी आवश्यकता है, इसलिए मैंने इसे भी शामिल किया है।
CREATE TABLE foo (
FieldA INT,
FieldB INT
);
DELIMITER //
CREATE TRIGGER InsertFieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
END IF;
END//
CREATE TRIGGER UpdateFieldABNotNull BEFORE UPDATE ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
END IF;
END//
DELIMITER ;
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
UPDATE foo SET FieldA = NULL; -- gives error
मैं एसक्यूएल सर्वर में कुछ इसी तरह किया है, मैं अगर यह MySQL में सीधे काम करेंगे यकीन नहीं है, लेकिन:
ALTER TABLE tableName ADD CONSTRAINT constraintName CHECK ((fieldA IS NOT NULL) OR (fieldB IS NOT NULL));
कम से कम मुझे विश्वास है कि वाक्य रचना है।
हालांकि, ध्यान रखें कि आप टेबल पर चेक बाधाएं नहीं बना सकते हैं, आप केवल एक तालिका के भीतर कॉलम देख सकते हैं।
इस तरह की कोई समस्या के लिए मानक वाक्य रचना है, लेकिन MySQL आनंदपूर्वक बाधा पर ध्यान नहीं देता बाद में
ALTER TABLE `generic`
ADD CONSTRAINT myConstraint
CHECK (
`FieldA` IS NOT NULL OR
`FieldB` IS NOT NULL
)
@Sklivvz: MySQL 5.0.51a साथ परीक्षण, मैं इसे एक चेक बाधा को पार्स करता है, लेकिन लागू नहीं करता है लगता है यह। मैं कोई त्रुटि के साथ (पूर्ण, पूर्ण) सम्मिलित कर सकते हैं। MyISAM और InnoDB दोनों का परीक्षण किया। इसके बाद SHOW CREATE तालिका का उपयोग करके पता चलता है कि एक जांच बाधा तालिका परिभाषा में नहीं है, भले ही तालिका को परिभाषित करते समय कोई त्रुटि नहीं दी गई हो।
यह MySQL manual से मेल खाता है जो कहता है: "चेक खंड को पार्स किया गया है लेकिन सभी स्टोरेज इंजनों द्वारा अनदेखा किया गया है।"
तो MySQL के लिए, आपको इस नियम को लागू करने के लिए एक ट्रिगर का उपयोग करना होगा। एकमात्र समस्या यह है कि MySQL ट्रिगर्स के पास कोई त्रुटि बढ़ाने या INSERT ऑपरेशन को निरस्त करने का कोई तरीका नहीं है। एक त्रुटि के कारण ट्रिगर में आप एक चीज कर सकते हैं नल के लिए न्यूल कॉलम सेट करना है।
CREATE TABLE foo (
FieldA INT,
FieldB INT,
FieldA_or_FieldB TINYINT NOT NULL;
);
DELIMITER //
CREATE TRIGGER FieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SET NEW.FieldA_or_FieldB = NULL;
ELSE
SET NEW.FieldA_or_FieldB = 1;
END IF;
END//
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
आपको अद्यतन से पहले एक समान ट्रिगर की भी आवश्यकता है।
विधेयक, मेरे उत्तर को तदनुसार, धन्यवाद, – Sklivvz
त्रुटि को बल देने के लिए 'न्यूल न्यूल' कॉलम का उपयोग करने के बजाय, आप 'SET NEW.FieldA = 1/0' जैसे कुछ कर सकते हैं जो एक विभाजन-दर-शून्य त्रुटि फेंक देगा । एक बहुत ही उपयोगी * त्रुटि संदेश नहीं है, लेकिन कम से कम आपको विशेष कॉलम जोड़ने की ज़रूरत नहीं है। मैं वास्तव में चाहता हूं कि MySQL उचित 'जांच' बाधाओं का समर्थन करता है, या कम से कम ट्रिगर्स से त्रुटियों को फेंकने का एक बेहतर तरीका था। :( – friedo
@friedo: चूंकि ओपी का सवाल कुछ विशेष गैर-शून्य स्थितियों को लागू करने के बारे में था, मैंने सोचा कि एक शून्य उल्लंघन त्रुटि संदेश उचित होगा। एक और चाल जो आप MySQL ट्रिगर में कर सकते हैं, ट्रिगर में एक पूर्णांक चर घोषित करता है और कोशिश करता है इसे एक स्ट्रिंग असाइन करने के लिए। यह एक त्रुटि संदेश उठाता है जिसमें आपके द्वारा उपयोग की जाने वाली स्ट्रिंग शामिल है। :) –
यह आपके प्रश्न का उत्तर नहीं है, लेकिन कुछ अतिरिक्त जानकारी है।
अनेक कॉलम के साथ काम कर और पता चल सके कि सभी रिक्त हैं या एक अशक्त नहीं है, मैं आम तौर पर COALESCE()
का उपयोग करें - यह, संक्षिप्त पठनीय और आसानी से maintainable अगर सूची बढ़ता है:
COALESCE(a, b, c, d) IS NULL -- True if all are NULL
COALESCE(a, b, c, d) IS NOT NULL -- True if any one is not null
इस में इस्तेमाल किया जा सकता आपका ट्रिगर
चूंकि यह मानक SQL वाक्यविन्यास है, इसलिए यह अन्य SQL- आधारित डेटाबेस के साथ भी काम करना चाहिए। (यह निश्चित रूप से PostgreSQL के लिए काम करता है।) – Neall
MySQL मैनुअल कहता है: "चेक खंड को पार्स किया गया है लेकिन सभी स्टोरेज इंजनों द्वारा अनदेखा किया गया है।" मैंने कोशिश की और यह सच है। –
इन्हें इनो डीबी टेबल के लिए भी अनदेखा किया गया है? वह बेकार है। – Neall