MySQL में CHECK बाधा काम नहीं कर रही है


126

पहले मैंने एक टेबल बनाया जैसे

CREATE TABLE Customer (
  SD integer CHECK (SD > 0),
  Last_Name varchar (30),
  First_Name varchar(30)
);

और फिर उस तालिका में मान डाले

INSERT INTO Customer values ('-2','abc','zz');

MySQL त्रुटि नहीं दिखाता है, इसने मानों को स्वीकार कर लिया है।


आंशिक रूप से सहमत हैं। यह देखते हुए कि आपने इसका उपयोग करने की कोशिश की, यह माना जा सकता है कि आप दोनों प्रश्न पूछ रहे थे। वास्तव में, आपने जो उत्तर स्वीकार किया है, वह मुख्य रूप से समझा रहा है कि यह काम क्यों नहीं करता है।
igorrs

1
आप इस सुविधा के अनुरोध पर मतदान कर सकते हैं: Bugs.mysql.com/bug.php?id=3464 लेकिन इसने एक दशक में कोई ध्यान नहीं दिया।
जारेड बेक

11
आप संस्करण 10.2.1 से MariaDB में CHECK बाधाओं का उपयोग कर सकते हैं ।
जोंक

जवाबों:


140

MySQL 8.0.16 पहला संस्करण है जो CHECK बाधाओं का समर्थन करता है।

Https://dev.mysql.com/doc/refman/8.0/en/create-table-check-concrain/.html पढ़ें

यदि आप MySQL 8.0.15 या पहले का उपयोग करते हैं, तो MySQL संदर्भ मैनुअल कहता है:

CHECKखंड पार्स लेकिन सभी भंडारण इंजन द्वारा नजरअंदाज कर दिया है।

ट्रिगर का प्रयास करें ...

mysql> delimiter //
mysql> CREATE TRIGGER trig_sd_check BEFORE INSERT ON Customer 
    -> FOR EACH ROW 
    -> BEGIN 
    -> IF NEW.SD<0 THEN 
    -> SET NEW.SD=0; 
    -> END IF; 
    -> END
    -> //
mysql> delimiter ;

उम्मीद है की वो मदद करदे।


9
यहाँ आप पाएंगे कि इसके बजाय एक त्रुटि को कैसे ट्रिगर किया जाए: stackoverflow.com/a/7189396/1144966
petermeissner

41
यह उन कारणों में से एक है, जो मैं MySQL के बजाय हमेशा PostgreSQL का उपयोग करूंगा, जो कि एक विकल्प है।
रेनडिएन

5
मुझे आश्चर्य है कि अगर पार्सर CHECKपरिभाषित बाधा का सामना करता है तो चेतावनी देने के लिए MySQL में 10 मिनट या 15 मिनट का विकास होगा । आह, यह बहुत सीधा होगा ...
गाबर्सच

75

दुर्भाग्य से MySQL SQL चेक बाधाओं का समर्थन नहीं करता है। आप संगतता कारणों से उन्हें अपनी DDL क्वेरी में परिभाषित कर सकते हैं, लेकिन उन्हें अनदेखा किया जाता है।

एक सरल विकल्प है

आप बना सकते हैं BEFORE INSERTऔर BEFORE UPDATEट्रिगर कर सकते हैं जो या तो एक त्रुटि का कारण बनता है या डेटा की आवश्यकताओं को पूरा नहीं होने पर फ़ील्ड को इसके डिफ़ॉल्ट मान पर सेट करता है।

BEFORE INSERTMySQL 5.5 के बाद काम करने के लिए उदाहरण

DELIMITER $$
CREATE TRIGGER `test_before_insert` BEFORE INSERT ON `Test`
FOR EACH ROW
BEGIN
    IF CHAR_LENGTH( NEW.ID ) < 4 THEN
        SIGNAL SQLSTATE '12345'
            SET MESSAGE_TEXT := 'check constraint on Test.ID failed';
    END IF;
END$$   
DELIMITER ;  

MySQL 5.5 से पहले आपको एक त्रुटि का कारण बनना था, जैसे कि एक अपरिभाषित प्रक्रिया।

दोनों मामलों में यह एक अंतर्निहित लेनदेन रोलबैक का कारण बनता है। MySQL प्रक्रियाओं और ट्रिगर्स के भीतर ही ROLLBACK स्टेटमेंट की अनुमति नहीं देता है।

यदि आप लेन-देन को रोलबैक नहीं करना चाहते हैं (INSERT / UPDATE को एक असफल "चेक बाधा" के साथ भी पास होना चाहिए, तो आप उस मान को अधिलेखित कर सकते हैं SET NEW.ID = NULLजो आईडी को फ़ील्ड डिफ़ॉल्ट मान पर सेट करेगा, वास्तव में आईडी के लिए कोई मतलब नहीं है यद्यपि

संपादित करें: आवारा उद्धरण हटाया।

:=ऑपरेटर के बारे में :

इसके विपरीत =, :=ऑपरेटर की तुलना ऑपरेटर के रूप में कभी नहीं की जाती है। इसका मतलब है कि आप :=किसी वैल्यू को असाइन करने के लिए किसी भी मान्य एसक्यूएल स्टेटमेंट (सिर्फ सेट स्टेटमेंट में नहीं) का उपयोग कर सकते हैं ।

https://dev.mysql.com/doc/refman/5.6/en/assignment-operators.html

संबंधित पहचानकर्ता उद्धरण के बारे में:

पहचानकर्ता उद्धरण वर्ण बैकटिक है ("` ")

यदि ANSI_QUOTES SQL मोड सक्षम है, तो पहचानकर्ताओं को दोहरे उद्धरण चिह्नों के भीतर उद्धृत करना भी अनुमत है

http://dev.mysql.com/doc/refman/5.6/en/identifiers.html


7
... बहुत सरल नहीं है, कम से कम CHECK :( की तुलना में। Coupla tutes: net.tutsplus.com/tutorials/dat डेटाबेस / , sitepoint.com/how-to-create-mysql-triggers
Ben

उह यह बहुत भारी लग रहा है। मुझे लगता है कि मैं इसके बजाय अजगर में एक ट्यूपल बनाता हूं और इसे डालने के बजाय वहां मूल्यों की जांच करता
हूं

त्वरित प्रश्न: यह सेटिंग के बिना काम क्यों नहीं करता है DELIMITER?
ddz

52

CHECK MySQL द्वारा बाधाओं को नजरअंदाज कर दिया जाता है जैसा कि डॉक्स में एक छोटी सी टिप्पणी में समझाया गया है: CREATE TABLE

CHECKखंड पार्स लेकिन सभी भंडारण इंजन द्वारा नजरअंदाज कर दिया है।


2
@ वेफिलो: सही, अन्य DBMS में CHECKबाधाओं के सही कार्यान्वयन के साथ , यदि CHECKमूल्यांकन FALSEतब सम्मिलित (या अद्यतन) नहीं किया जाता है और एक त्रुटि होती है।
ypercube y

MariaDB में फिक्स्ड (यह उत्तर देखें stackoverflow.com/a/44333349 )।
जेरेमी

@ Jérôme मुझे पता है, मेरे पास कुछ (अधिक हाल के) उत्तर हैं जिनमें इस क्षेत्र में सुधार शामिल हैं (मारियाडीबी और माईएसक्यूएल में दोनों ने इस मुद्दे को हल करने के अन्य तरीके भी शामिल किए हैं, इससे पहले कि मारबीडीबी ने CHECK बाधाओं को ठीक से लागू किया है)। मुझे यकीन नहीं है कि मुझे जाना चाहिए और मेरे सभी पुराने उत्तरों को संपादित करना चाहिए!
ypercube y

मुझे लगता है कि मेरी टिप्पणी अधिक हाल के उत्तर के लिंक के साथ ठीक है। या कुछ भी नहीं से बेहतर है। शायद मुझे संपादित करना चाहिए था। मैं कुछ भी करने के लिए आप पर दबाव डालने का मतलब नहीं था।
Jérôme



1

चेक बाधाओं को संस्करण 8.0.15 के रूप में समर्थित किया गया है (अभी तक जारी नहीं किया गया है)

https://bugs.mysql.com/bug.php?id=3464

[२३ जनवरी १६:२४] पॉल ड्युबॉइस

डेवलपर द्वारा पोस्ट: 8.0.15 में फिक्स्ड।

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


1

MySQL 8.0.16 का उपयोग करने के लिए अद्यतन करें checks:

MySQL 8.0.16 के अनुसार, CREATE टेबल सभी स्टोरेज इंजनों के लिए टेबल और कॉलम CHECK बाधाओं की मुख्य विशेषताओं की अनुमति देता है। तालिका तालिका और स्तंभ बाधाओं दोनों के लिए बनाएँ तालिका निम्नलिखित चेक बाधा सिंटैक्स की अनुमति देती है

MySQL डॉक्यूमेंटेशन चेक करता है


-2

set sql_mode = 'STRICT_TRANS_TABLES'OR के साथ प्रयास करेंSET sql_mode='STRICT_ALL_TABLES'


2
यह गलत प्रकार का डेटा दर्ज लेकिन डेटा है कि पूरा नहीं करता है में प्रवेश करने की नहीं रोकता है कि actuall मदद (MySQL 5.6) नहीं है CHECKबाधा
petermeissner
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.