डेटा मैनेज करना एक बड़ी चुनौती है। जैसे-जैसे हमारी दुनिया बदलती है, डेटा व्यापक, प्रचुर और गहन होता जा रहा है। इसलिए, हमें बाढ़ से निपटने के उपाय करने चाहिए।
डेटा के हर एक टुकड़े को 'हाथ से मान्य करना ' घड़ी के आसपास बस अव्यावहारिक है। क्या शानदार सपना है। लेकिन, आखिर बात बस इतनी ही है। एक सपना। खराब डेटा खराब डेटा है। कोई फर्क नहीं पड़ता कि आप इसे कैसे काटते हैं या इसे पासा करते हैं (सजा का इरादा)। यह शुरू से ही एक समस्या है, जिसके कारण और भी अधिक समस्याएं होती हैं।
आधुनिक डेटाबेस अधिकांश भारी भारोत्तोलन . को संभालते हैं हमारे लिए। कई डेटा के इस विशेष क्षेत्र को प्रबंधित करने में सहायता के लिए अंतर्निहित समाधान प्रदान करते हैं।
किसी तालिका के कॉलम में दर्ज किए गए डेटा को नियंत्रित करने का एक निश्चित तरीका डेटा प्रकार है। दशमलव संख्या वाले कॉलम की आवश्यकता है, जिसमें कुल अंकों की संख्या 4 हो, जिनमें से 2 दशमलव के बाद हों?
अवश्य! कोई समस्या नहीं है।
NUMERIC(4,2), एक व्यवहार्य विकल्प, एक प्रहरी की तरह उस स्तंभ की रखवाली कर रहा है। क्या चरित्र पाठ मान वहां खिसक सकते हैं? स्नोबॉल का मौका नहीं है।
PostgreSQL कई प्रकार के डेटा प्रकार प्रदान करता है। संभावना है, आपकी ज़रूरतों को पूरा करने के लिए एक पहले से मौजूद है। यदि नहीं, तो आप अपना खुद का बना सकते हैं। (देखें:पोस्टग्रेएसक्यूएल क्रिएट टाइप)
फिर भी, अकेले डेटा प्रकार पर्याप्त नहीं हैं। आप आश्वस्त नहीं कर सकते कि सबसे विशिष्ट आवश्यकताओं को कवर किया गया है और इस तरह की व्यापक संरचना के अनुरूप है। स्कीमा डिज़ाइन करते समय अनुपालन नियम और कुछ प्रकार के 'मानक' की आवश्यकता होती है।
मान लीजिए कि उसी NUMERIC(4,2) कॉलम में, आप केवल 25.25 से अधिक लेकिन 74.33 से कम मान चाहते हैं? घटना में, मान 88.22 संग्रहीत किया जाता है, डेटा प्रकार गलती पर नहीं है। दशमलव के बाद अधिकतम 2 अंकों के साथ 4 कुल अंकों की अनुमति देकर, यह अपना काम कर रहा है। दोष कहीं और लगाओ।
जब हमारे डेटाबेस में अनुमत डेटा को नियंत्रित करने की बात आती है तो हम इस मोर्चे पर कैसे जीतते हैं? डेटा स्थिरता सर्वोच्च प्राथमिकता है और किसी भी ध्वनि डेटा समाधान के लिए अभिन्न है। (बंद) मौके पर आपने एकत्र किए गए डेटा को उसके मूल स्रोत की शुरुआत से नियंत्रित किया, स्थिरता एक समस्या से कम होने की संभावना है।
लेकिन, एक संपूर्ण दुनिया केवल उन कई काल्पनिक उपन्यासों में से एक में मौजूद है (शायद) जिन्हें मैं पढ़ना पसंद करता हूं।
दुर्भाग्य से अधूरा, असंगत, और 'गंदा' डेटा डेटाबेस-केंद्रित क्षेत्र में मौजूद सभी सामान्य विशेषताएं और वास्तविकताएं हैं।
हालाँकि, सभी कयामत और निराशा में नहीं खोए हैं क्योंकि हमारे पास इन मुद्दों को कम करने के लिए चेक की कमी है। उन विशिष्ट नियमों के लिए, हमें आवश्यकता से बाहर होना चाहिए, जो सुनिश्चित करता है कि हम केवल सुसंगत डेटा को संभालें और संग्रहीत करें। डेटाबेस में उन विशिष्टताओं को अनिवार्य करके, हम असंगत डेटा के प्रभाव को हमारे व्यावसायिक लक्ष्यों और आगे ले जाने वाले समाधानों पर कम कर सकते हैं।
बाधा क्या है? - एक उच्च स्तरीय परिभाषा
इस संदर्भ में, एक बाधा एक प्रकार का नियम या प्रतिबंध है जो डेटाबेस तालिका स्तंभ पर रखा जाता है। इस विशिष्टता के लिए आवश्यक है कि आने वाले डेटा को संग्रहीत होने से पहले निर्धारित आवश्यकता (आवश्यकताओं) का पालन करना चाहिए। कहा गया है कि आवश्यकताएँ 'पेशेवर रूप से' गढ़ी जाती हैं (और अक्सर होती हैं) व्यावसायिक नियमों के रूप में . यह सत्य के लिए एक सत्यापन बूलियन परीक्षण के लिए उबलता है। यदि डेटा गुजरता है (सत्य), यह संग्रहीत है। यदि नहीं, तो नो एंट्री (झूठी)।
PostgreSQL में उपलब्ध बाधाएं
लेखन के समय, PostgreSQL दस्तावेज़ीकरण 6 श्रेणियों की बाधाओं को सूचीबद्ध करता है।
वे हैं:
- बाधाओं की जांच करें
- अशक्त प्रतिबंध नहीं
- अद्वितीय बाधाएं
- प्राथमिक कुंजी
- विदेशी कुंजी
- बहिष्करण प्रतिबंध
बाधाओं की जांच करें
INTEGER कॉलम के लिए एक सरल उदाहरण मान 100 से अधिक मानों को अस्वीकार करना होगा।
learning=> CREATE TABLE no_go(id INTEGER CHECK (id < 100));
CREATE TABLE
learning=> INSERT INTO no_go(id) VALUES(101);
ERROR: new row for relation "no_go" violates check constraint "no_go_id_check"
DETAIL: Failing row contains (101).
जैसा कि ऊपर देखा गया है, चेक बाधा का उल्लंघन करने वाले किसी भी मान को INSERT करने का प्रयास विफल हो जाता है।
चेक बाधाओं को न केवल INSERT के दौरान कॉलम की निगरानी करनी चाहिए, यहां तक कि अद्यतन विवरण (और अन्य जैसे, \ copy और COPY) को भी प्रतिबंधों का पालन करना चाहिए।
मान लीजिए कि no_go तालिका का यह मान है:
learning=> TABLE no_go;
id
----
55
(1 row)
आईडी कॉलम मान पर एक अद्यतन जो चेक बाधा के अनुरूप नहीं है वह भी विफल रहता है:
learning=> UPDATE no_go SET id = 155
learning-> WHERE id = 55;
ERROR: new row for relation "no_go" violates check constraint "no_go_id_check"
DETAIL: Failing row contains (155).
लक्ष्य कॉलम डेटा प्रकार के लिए बाधाओं की जाँच करें 'समझ में' होना चाहिए। टेक्स्ट मानों को संग्रहीत करने पर रोक लगाने के लिए INTEGER कॉलम का प्रयास करना और बाधित करना अमान्य है क्योंकि डेटा प्रकार स्वयं इसकी अनुमति नहीं देगा।
इस उदाहरण को देखें जहां मैं टेबल निर्माण के दौरान उस प्रकार की चेक बाधा को लागू करने का प्रयास करता हूं:
learning=> CREATE TABLE num_try(id INTEGER CHECK(id IN ('Bubble', 'YoYo', 'Jack-In-The-Box')));
ERROR: invalid input syntax for integer: "Bubble"
चेक बाधाओं के बिना जीवन
एक पुरानी कहावत मैंने सुनी है जो मेरे साथ प्रतिध्वनित होती है:"जब तक कुआं सूख नहीं जाता, तब तक आपको पानी नहीं छोड़ना चाहिए . "
चेक बाधाओं के बिना, हम निश्चित रूप से उनके उल्लेखनीय लाभ के लिए संबंधित हो सकते हैं, जब आपको उनके बिना करना होता है तो इसकी सराहना की जाती है।
यह उदाहरण लें...
शुरू करने के लिए हमारे पास यह तालिका और डेटा है जो ट्रेल सतह सामग्री का प्रतिनिधित्व करता है:
learning=> SELECT * FROM surface_material;
surface_id | material
------------+--------------
101 | Gravel
202 | Grass
303 | Dirt
404 | Turf
505 | Concrete
606 | Asphalt
707 | Clay
808 | Polyurethane
(8 rows)
और यह तालिका निशान नामों और इसकी सतह_आईडी के साथ:
learning=> SELECT * FROM trails;
id | name | surface_id
----+-----------------+------------
1 | Dusty Storm | 303
2 | Runners Trip | 808
3 | Pea Gravel Pass | 101
4 | Back 40 Loop | 404
(4 rows)
हम आश्वस्त करना चाहते हैं कि टेबल ट्रेल्स में टेबल सरफेस_मटेरियल में संबंधित मानों के लिए केवल सरफेस_आईडी शामिल हैं।
हां हां मुझे पता है। तुम मुझ पर चिल्ला रहे हो।
"क्या इस पर ध्यान नहीं दिया जा सकता विदेशी कुंजी?!?"
हाँ, यह कर सकते हैं। लेकिन मैं इसका उपयोग एक सामान्य उपयोग को प्रदर्शित करने के लिए कर रहा हूं, साथ ही जानने के लिए एक नुकसान (बाद में पोस्ट में उल्लेख किया गया है)।
चेक बाधाओं के बिना, आप एक TRIGGER का सहारा ले सकते हैं और असंगत मानों को संग्रहीत होने से रोक सकते हैं।
यहाँ एक कच्चा (लेकिन काम कर रहा) उदाहरण है:
CREATE OR REPLACE FUNCTION check_me()
RETURNS TRIGGER AS
$$
BEGIN
IF NEW.surface_id NOT IN (SELECT surface_id FROM surface_material)
THEN Raise Exception '% is not allowed for surface id', NEW.surface_id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE PLpgSQL;
CREATE TRIGGER check_me BEFORE INSERT OR UPDATE ON trails
FOR EACH ROW EXECUTE PROCEDURE check_me();
एक मान INSERT करने का प्रयास विफल हो जाता है जिसमें तालिका ट्रेल्स में एक समान सतह_आईडी नहीं है:
learning=> INSERT INTO trails(name, surface_id)
learning-> VALUES ('Tennis Walker', 110);
ERROR: 110 is not allowed for surface id
CONTEXT: PL/pgSQL function check_me() line 4 at RAISE
नीचे दिए गए क्वेरी परिणाम 'अपमानजनक . की पुष्टि करते हैं ' मान संग्रहीत नहीं किया गया था:
learning=> SELECT * FROM trails;
id | name | surface_id
----+-----------------+------------
1 | Dusty Storm | 303
2 | Runners Trip | 808
3 | Pea Gravel Pass | 101
4 | Back 40 Loop | 404
(4 rows)
अवांछित मूल्यों को प्रतिबंधित करने के लिए यह निश्चित रूप से बहुत काम है।
आइए इस आवश्यकता को एक चेक बाधा के साथ फिर से लागू करें।
चूंकि आप वास्तविक चेक बाधा परिभाषा में एक सबक्वायरी का उपयोग नहीं कर सकते हैं (यहां मैंने उपरोक्त उदाहरण का उपयोग किया है), मान हार्ड-कोडेड होना चाहिए। ।
एक छोटी सी मेज के लिए, या तुच्छ उदाहरण जैसे कि यहां प्रस्तुत किया गया है, यह ठीक है। अन्य परिदृश्यों में, अधिक मूल्यों को शामिल करते हुए, आपको वैकल्पिक समाधान खोजने के लिए बेहतर सेवा दी जा सकती है।
learning=> ALTER TABLE trails ADD CONSTRAINT t_check CHECK (surface_id IN (101, 202, 303, 404, 505, 606, 707, 808));
ALTER TABLE
यहाँ मैंने चेक बाधा t_check नाम दिया है बनाम सिस्टम को इसे नाम देने दे रहा है।
(नोट:पहले से परिभाषित check_me() फ़ंक्शन और साथ में नीचे चलाने से पहले TRIGGER गिराए गए (दिखाए नहीं गए) INSERT.)
learning=> INSERT INTO trails(name, surface_id)
VALUES('Tennis Walker', 110);
ERROR: new row for relation "trails" violates check constraint "t_check"
DETAIL: Failing row contains (7, Tennis Walker, 110).
क्या आप देखेंगे कि यह कितना आसान था! कोई ट्रिगर और फ़ंक्शन की आवश्यकता नहीं है।
चेक की कमी इस प्रकार के काम को आसान बनाती है।
चेक बाधा परिभाषा में चालाक होना चाहते हैं?
आप कर सकते हैं।
मान लीजिए कि आपको एक टेबल लिस्टिंग ट्रेल्स की आवश्यकता है जो संवेदनशील टखनों और घुटनों वाले लोगों के लिए थोड़े दयालु हों। यहां कोई कठोर सतह वांछित नहीं है।
आप आश्वस्त करना चाहते हैं कि तालिका में सूचीबद्ध किसी भी हाइकिंग ट्रेल या ट्रैक में 'बजरी' या 'गंदगी' की सतह सामग्री है।
यह चेक बाधा उस आवश्यकता को संभालती है कोई समस्या नहीं:
learning=> CREATE TABLE nice_trail(id SERIAL PRIMARY KEY,
learning(> name TEXT, mat_surface_id INTEGER CONSTRAINT better_surface CHECK(id IN (101, 303)));
CREATE TABLE
यह बिल्कुल ठीक काम करता है।
लेकिन, एक ऐसे फंक्शन के बारे में जो चेक को काम करने के लिए आवश्यक दोनों आईडी लौटाता है? क्या चेक बाधा परिभाषा में फ़ंक्शन की अनुमति है?
हां, एक को शामिल किया जा सकता है।
यहां एक कार्यशील उदाहरण दिया गया है।
सबसे पहले, फंक्शन बॉडी और परिभाषा:
CREATE OR REPLACE FUNCTION easy_hike(id INTEGER)
RETURNS BOOLEAN AS
$$
BEGIN
IF id IN (SELECT surface_id FROM surface_material WHERE material IN ('Gravel', 'Dirt'))
THEN RETURN true;
ELSE RETURN false;
END IF;
END;
$$ LANGUAGE PLpgSQL;
इस क्रिएट टेबल स्टेटमेंट में नोटिस, मैं 'टेबल . पर चेक बाधा को परिभाषित करता हूं ' स्तर जबकि पहले मैंने केवल 'कॉलम . पर उदाहरण दिए हैं ' स्तर।
तालिका स्तर पर परिभाषित चेक बाधाएँ पूरी तरह से मान्य हैं:
learning=> CREATE TABLE nice_trail(nt_id SERIAL PRIMARY KEY,
learning(> name TEXT, mat_surface_id INTEGER,
learning(> CONSTRAINT better_surface_check CHECK(easy_hike(mat_surface_id)));
CREATE TABLE
ये सभी प्रविष्टियां अच्छी हैं:
learning=> INSERT INTO nice_trail(name, mat_surface_id)
learning-> VALUES ('Smooth Rock Loop', 101), ('High Water Bluff', 303);
INSERT 0 2
अब एक INSERT के साथ एक ट्रेल के लिए आता है जो कॉलम mat_surface_id पर प्रतिबंध को पूरा नहीं करता है:
learning=> INSERT INTO nice_trail(name, mat_surface_id)
learning-> VALUES('South Branch Fork', 404);
ERROR: new row for relation "nice_trail" violates check constraint "better_surface_check"
DETAIL: Failing row contains (3, South Branch Fork, 404).
चेक बाधा परिभाषा में हमारा FUNCTION कॉल अवांछित कॉलम मानों को प्रतिबंधित करते हुए, डिज़ाइन के अनुसार काम करता है।
धुआं और दर्पण?
क्या सब कुछ वैसा ही है जैसा कि चेक बाधाओं के साथ लगता है? सब ब्लैक एंड व्हाइट? सामने कोई मुखौटा नहीं है?
ध्यान देने योग्य उदाहरण।
हमारे पास एक साधारण तालिका है जिसमें हम चाहते हैं कि मौजूद INTEGER कॉलम के लिए DEFAULT मान 10 हो:
learning=> CREATE TABLE surprise(id INTEGER DEFAULT 10, CHECK (id <> 10));
CREATE TABLE
लेकिन, मैंने एक चेक बाधा भी शामिल की है जो 10 के मान को प्रतिबंधित करती है, आईडी को परिभाषित करके उस संख्या के बराबर नहीं हो सकता है।
कौन दिन जीत जाएगा? डिफ़ॉल्ट या चेक बाधा?
आपको यह जानकर आश्चर्य हो सकता है कि यह कौन सा है।
मैं था।
एक मनमाना INSERT, ठीक काम कर रहा है:
learning=> INSERT INTO surprise(id) VALUES(17);
INSERT 0 1
learning=> SELECT * FROM surprise;
id
----
17
(1 row)
और डिफ़ॉल्ट मान वाला INSERT:
learning=> INSERT INTO surprise(id) VALUES(DEFAULT);
ERROR: new row for relation "surprise" violates check constraint "surpise_id_check"
DETAIL: Failing row contains (10).
उफ़...
फिर से, एक वैकल्पिक सिंटैक्स के साथ:
learning=> INSERT INTO surprise DEFAULT VALUES;
ERROR: new row for relation "surprise" violates check constraint "surpise_id_check"
DETAIL: Failing row contains (10).
चेक बाधा DEFAULT मान पर जीत हासिल करती है।
ऑडबॉल उदाहरण
निर्माण के दौरान तालिका परिभाषा में चेक बाधा कहीं भी बहुत अधिक दिखाई दे सकती है। यहां तक कि कॉलम स्तर पर भी, इसे ऐसे कॉलम पर सेट किया जा सकता है जो चेक में शामिल न हो।
उदाहरण के लिए यहां एक उदाहरण दिया गया है:
learning=> CREATE TABLE mystery(id_1 INTEGER CHECK(id_2 > id_3),
learning(> id_2 INTEGER, id_3 INTEGER);
CREATE TABLE
बाधा का परीक्षण करने के लिए एक INSERT:
learning=> INSERT INTO mystery(id_1, id_2, id_3) VALUES (1, 2, 3);
ERROR: new row for relation "mystery" violates check constraint "mystery_check"
DETAIL: Failing row contains (1, 2, 3).
इरादा के अनुसार काम करता है।
सत्यापन और मान्य नहीं
हमारे पास यह सरल तालिका और डेटा है:
learning=> CREATE TABLE v_check(id INTEGER);
CREATE TABLE
learning=> INSERT INTO v_check SELECT * FROM generate_series(1, 425);
INSERT 0 425
मान लीजिए कि अब हमें एक चेक बाधा लागू करने की आवश्यकता है जो 50 से कम किसी भी मान को प्रतिबंधित करती है।
कल्पना कीजिए कि यह उत्पादन में एक बड़ी तालिका है और हम वास्तव में इस समय किसी भी अधिग्रहीत लॉक को बर्दाश्त नहीं कर सकते हैं, जिसके परिणामस्वरूप ALTER TABLE स्टेटमेंट होता है। लेकिन, आगे बढ़ते हुए, इस बाधा को दूर करने की जरूरत है।
ALTER TABLE एक लॉक प्राप्त करेगा (प्रत्येक भिन्न सबफ़ॉर्म पर निर्भर)। जैसा कि उल्लेख किया गया है, यह तालिका उत्पादन में है, इसलिए हम तब तक इंतजार करना चाहते हैं जब तक हम 'पीक घंटे से बाहर नहीं हो जाते। '।
चेक बाधा उत्पन्न करते समय आप मान्य नहीं विकल्प का उपयोग कर सकते हैं:
learning=> ALTER TABLE v_check ADD CONSTRAINT fifty_chk CHECK(id > 50) NOT VALID;
ALTER TABLE
आज श्वेतपत्र डाउनलोड करें क्लस्टरकंट्रोल के साथ पोस्टग्रेएसक्यूएल प्रबंधन और स्वचालन इस बारे में जानें कि पोस्टग्रेएसक्यूएल को तैनात करने, मॉनिटर करने, प्रबंधित करने और स्केल करने के लिए आपको क्या जानना चाहिए। श्वेतपत्र डाउनलोड करें निरंतर संचालन, एक INSERT या अद्यतन के लिए प्रयास करना चाहिए जो चेक बाधा का उल्लंघन करता है:
learning=> INSERT INTO v_check(id) VALUES(22);
ERROR: new row for relation "v_check" violates check constraint "fifty_chk"
DETAIL: Failing row contains (22).
'अपमानजनक' कॉलम मान निषिद्ध है।
फिर, डाउनटाइम के दौरान, हम उल्लंघन में हो सकने वाले (किसी भी) पूर्व-मौजूदा कॉलम के खिलाफ इसे लागू करने के लिए चेक बाधा को मान्य करते हैं:
learning=> ALTER TABLE v_check VALIDATE CONSTRAINT fifty_chk;
ERROR: check constraint "fifty_chk" is violated by some row
मेरी राय में संदेश काफी गूढ़ है। लेकिन, यह हमें सूचित करता है कि ऐसी पंक्तियाँ हैं जो बाधाओं के अनुपालन में नहीं हैं।
यहाँ कुछ मुख्य बिंदु दिए गए हैं जिन्हें मैं ALTER TABLE दस्तावेज़ीकरण से शामिल करना चाहता था (उद्धरण में डॉक्स से सीधे शब्द):
- वाक्यविन्यास:ADD table_constraint [ NOT VALID ] - साथ में विवरण (आंशिक) "यह प्रपत्र तालिका बनाने के समान सिंटैक्स का उपयोग करके तालिका में एक नई बाधा जोड़ता है, साथ ही विकल्प मान्य नहीं है, जो वर्तमान में केवल विदेशी कुंजी के लिए अनुमत है और बाधाओं की जाँच करें। यदि बाधा को मान्य नहीं के रूप में चिह्नित किया गया है, तो यह सत्यापित करने के लिए संभावित-लंबी प्रारंभिक जाँच कि तालिका में सभी पंक्तियाँ बाधा को संतुष्ट करती हैं, छोड़ दिया गया है।"
- सिंटैक्स:VALIDATE CONSTRAINT Constraint_name - साथ में विवरण (आंशिक) "यह फॉर्म एक विदेशी कुंजी या चेक बाधा को मान्य करता है जिसे पहले NOT VALID के रूप में बनाया गया था, यह सुनिश्चित करने के लिए तालिका को स्कैन करके कि ऐसी कोई पंक्तियाँ नहीं हैं जिनके लिए बाधा संतुष्ट नहीं है। " "सत्यापन तालिका पर केवल एक साझा अद्यतन अनन्य लॉक प्राप्त करता है जिसे बदला जा रहा है।"
एक तरफ, ध्यान देने योग्य दो बिंदु मैंने रास्ते में सीखे। चेक बाधा परिभाषाओं में सेट-रिटर्निंग फ़ंक्शंस और सबक्वायरीज़ की अनुमति नहीं है। मुझे यकीन है कि अन्य भी हैं और मैं नीचे टिप्पणी में उन पर किसी भी प्रतिक्रिया का स्वागत करता हूं।
चेक बाधाएं कमाल की हैं। किसी भी डेटा प्रतिबंध को लागू करने के लिए, PostgreSQL डेटाबेस द्वारा प्रदान किए गए 'अंतर्निहित' समाधानों का उपयोग करना सही समझ में आता है। आवश्यक कॉलम (स्तंभों) के लिए चेक बाधाओं को लागू करने में लगने वाला समय और प्रयास, किसी को भी लागू न करने से कहीं अधिक है। इस प्रकार लंबे समय में समय की बचत होती है। इस प्रकार की आवश्यकताओं को संभालने के लिए हम जितना अधिक डेटाबेस पर निर्भर होंगे, उतना ही बेहतर होगा। हमें अपने संसाधनों को डेटाबेस प्रबंधन के अन्य क्षेत्रों/पहलुओं पर ध्यान केंद्रित करने और लागू करने में सक्षम बनाता है।
पढ़ने के लिए धन्यवाद।