PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

ORDBMS में "O":PostgreSQL इनहेरिटेंस

इस ब्लॉग प्रविष्टि में हम पोस्टग्रेएसक्यूएल इनहेरिटेंस से गुजरेंगे, जो परंपरागत रूप से पोस्टग्रेएसक्यूएल की शुरुआती रिलीज के बाद से शीर्ष विशेषताओं में से एक है। PostgreSQL में इनहेरिटेंस के कुछ विशिष्ट उपयोग हैं:

  • टेबल विभाजन
  • बहु-किरायेदारी

संस्करण 10 तक PostgreSQL ने वंशानुक्रम का उपयोग करके तालिका विभाजन को लागू किया। PostgreSQL 10 घोषणात्मक विभाजन का एक नया तरीका प्रदान करता है। इनहेरिटेंस का उपयोग करके पोस्टग्रेएसक्यूएल विभाजन एक बहुत ही परिपक्व तकनीक है, अच्छी तरह से प्रलेखित और परीक्षण किया गया है, हालांकि डेटा मॉडल के नजरिए से पोस्टग्रेएसक्यूएल में विरासत (मेरी राय में) इतनी व्यापक नहीं है, इसलिए हम इस ब्लॉग में अधिक क्लासिक उपयोग के मामलों पर ध्यान केंद्रित करेंगे। हमने पिछले ब्लॉग (पोस्टग्रेएसक्यूएल के लिए बहु-किरायेदारी विकल्प) से देखा कि बहु-किरायेदारी प्राप्त करने का एक तरीका अलग-अलग तालिकाओं का उपयोग करना और फिर उन्हें एक दृश्य के माध्यम से समेकित करना है। हमने इस डिजाइन की कमियां भी देखीं। इस ब्लॉग में हम इनहेरिटेंस का उपयोग करके इस डिज़ाइन को बेहतर बनाएंगे।

विरासत का परिचय

अलग-अलग तालिकाओं और विचारों के साथ लागू की गई बहु-किरायेदारी पद्धति को देखते हुए हमें याद आता है कि इसका प्रमुख नुकसान इन्सर्ट/अपडेट/डिलीट करने में असमर्थता है। जिस क्षण हम किराये . पर अपडेट करने का प्रयास करते हैं देखें कि हमें यह त्रुटि मिलेगी:

ERROR:  cannot insert into view "rental"
DETAIL:  Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable.
HINT:  To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.

इसलिए, हमें किराये . पर एक ट्रिगर या नियम बनाने की आवश्यकता होगी सम्मिलित/अद्यतन/हटाने को संभालने के लिए फ़ंक्शन निर्दिष्ट करना देखें। विकल्प विरासत का उपयोग करना है। आइए हम पिछले ब्लॉग का स्कीमा बदलें:

template1=# create database rentaldb_hier;
template1=# \c rentaldb_hier
rentaldb_hier=# create schema boats;
rentaldb_hier=# create schema cars;

अब मुख्य पैरेंट टेबल बनाते हैं:

rentaldb_hier=# CREATE TABLE rental (
    id integer NOT NULL,
    customerid integer NOT NULL,
    vehicleno text,
    datestart date NOT NULL,
    dateend date
); 

ओओ के संदर्भ में यह तालिका सुपरक्लास (जावा शब्दावली में) से मेल खाती है। अब विरासत में . द्वारा बच्चों की तालिका को परिभाषित करते हैं public.rental से और डोमेन के लिए विशिष्ट प्रत्येक तालिका के लिए एक कॉलम जोड़ना:उदा। कारों के मामले में अनिवार्य ड्राइवर (ग्राहक) लाइसेंस नंबर और वैकल्पिक नाव नौकायन प्रमाणपत्र।

rentaldb_hier=# create table cars.rental(driv_lic_no text NOT NULL) INHERITS (public.rental);
rentaldb_hier=# create table boats.rental(sail_cert_no text) INHERITS (public.rental);

दो टेबल cars.rental और नौका.किराया अपने माता-पिता से सभी कॉलम इनहेरिट करें public.rental :
 

rentaldb_hier=# \d cars.rental
                           Table "cars.rental"
     Column     |         Type          | Collation | Nullable | Default
----------------+-----------------------+-----------+----------+---------
 id             | integer               |           | not null |
 customerid     | integer               |           | not null |
 vehicleno      | text                  |           |          |
 datestart      | date                  |           | not null |
 dateend        | date                  |           |          |
 driv_lic_no | text                  |           | not null |
Inherits: rental
rentaldb_hier=# \d boats.rental
                         Table "boats.rental"
    Column    |         Type          | Collation | Nullable | Default
--------------+-----------------------+-----------+----------+---------
 id           | integer               |           | not null |
 customerid   | integer               |           | not null |
 vehicleno    | text                  |           |          |
 datestart    | date                  |           | not null |
 dateend      | date                  |           |          |
 sail_cert_no | text                  |           |          |
Inherits: rental

हमने देखा है कि हमने कंपनी . को छोड़ दिया है पैरेंट टेबल की परिभाषा में कॉलम (और इसके परिणामस्वरूप बच्चों की टेबल में भी)। अब इसकी आवश्यकता नहीं है क्योंकि किरायेदार की पहचान तालिका के पूरे नाम में है! हम बाद में प्रश्नों में इसका पता लगाने का एक आसान तरीका देखेंगे। अब तीन तालिकाओं में कुछ पंक्तियाँ सम्मिलित करते हैं (हम ग्राहकों . उधार लेते हैं पिछले ब्लॉग से स्कीमा और डेटा):

rentaldb_hier=# insert into rental (id, customerid, vehicleno, datestart) VALUES(1,1,'SOME ABSTRACT PLATE NO',current_date);
rentaldb_hier=# insert into cars.rental (id, customerid, vehicleno, datestart,driv_lic_no) VALUES(2,1,'INI 8888',current_date,'gr690131');
rentaldb_hier=# insert into boats.rental (id, customerid, vehicleno, datestart) VALUES(3,2,'INI 9999',current_date);

अब देखते हैं कि टेबल में क्या है:

rentaldb_hier=# select * from rental ;
 id | customerid |       vehicleno        | datestart  | dateend
----+------------+------------------------+------------+---------
  1 |          1 | SOME ABSTRACT PLATE NO | 2018-08-31 |
  2 |          1 | INI 8888               | 2018-08-31 |
  3 |          2 | INI 9999               | 2018-08-31 |
(3 rows)
rentaldb_hier=# select * from boats.rental ;
 id | customerid | vehicleno | datestart  | dateend | sail_cert_no
----+------------+-----------+------------+---------+--------------
  3 |          2 | INI 9999  | 2018-08-31 |         |
(1 row)
rentaldb_hier=# select * from cars.rental ;
 id | customerid | vehicleno | datestart  | dateend | driv_lic_no
----+------------+-----------+------------+---------+-------------
  2 |          1 | INI 8888  | 2018-08-31 |         | gr690131
(1 row)

तो ऑब्जेक्ट ओरिएंटेड भाषाओं (जैसे जावा) में मौजूद विरासत की वही धारणा पोस्टग्रेएसक्यूएल में भी मौजूद है! हम इसके बारे में इस प्रकार सोच सकते हैं:
public.rental:superclass
cars.rental:subclass
boats.rental:subclass
row public.rental.id =1:उदाहरण public.rental
पंक्ति car.rental.id =2:कारों का उदाहरण। किराया और public.rental
पंक्ति नावें.rental.id =3:नावों का उदाहरण। किराया और सार्वजनिक। किराए पर लेना

चूंकि नावों की कतारें, किराये और कार किराए पर लेना भी सार्वजनिक किराए के उदाहरण हैं, इसलिए यह स्वाभाविक है कि वे सार्वजनिक किराये की पंक्तियों के रूप में दिखाई देते हैं। यदि हम केवल public.rental को छोड़कर केवल पंक्तियाँ चाहते हैं (दूसरे शब्दों में पंक्तियाँ सीधे public.rental पर डाली जाती हैं) तो हम इसे केवल कीवर्ड का उपयोग करके निम्नानुसार करते हैं:

rentaldb_hier=# select * from ONLY rental ;
 id | customerid |       vehicleno        | datestart  | dateend
----+------------+------------------------+------------+---------
  1 |          1 | SOME ABSTRACT PLATE NO | 2018-08-31 |
(1 row)

जावा और पोस्टग्रेएसक्यूएल के बीच एक अंतर यह है कि जहां तक ​​​​इनहेरिटेंस जाता है:जावा मल्टीपल इनहेरिटेंस का समर्थन नहीं करता है जबकि पोस्टग्रेएसक्यूएल करता है, यह एक से अधिक टेबल से इनहेरिट करना संभव है, इसलिए इस संबंध में हम टेबल के बारे में सोच सकते हैं जैसे इंटरफेस जावा में।

यदि हम पदानुक्रम में सटीक तालिका का पता लगाना चाहते हैं जहां एक विशिष्ट पंक्ति संबंधित है (जावा में obj.getClass ()। getName () के बराबर) तो हम टेबलॉइड विशेष कॉलम (संबंधित तालिका के ओआईडी) को निर्दिष्ट करके कर सकते हैं। एम>पीजीक्लास ), regclass में डाली गई जो तालिका का पूरा नाम देती है:

rentaldb_hier=# select tableoid::regclass,* from rental ;
   tableoid   | id | customerid |       vehicleno        | datestart  | dateend
--------------+----+------------+------------------------+------------+---------
 rental       |  1 |          1 | SOME ABSTRACT PLATE NO | 2018-08-31 |
 cars.rental  |  2 |          1 | INI 8888               | 2018-08-31 |
 boats.rental |  3 |          2 | INI 9999               | 2018-08-31 |
(3 rows)

उपरोक्त (अलग-अलग टेबलॉइड) से हम यह अनुमान लगा सकते हैं कि पदानुक्रम में तालिकाएँ केवल पुरानी पुरानी PostgreSQL तालिकाएँ हैं, जो एक विरासत संबंध से जुड़ी हैं। लेकिन इसके अलावा, वे काफी हद तक सामान्य तालिकाओं की तरह काम करते हैं। और अगले भाग में इस पर और जोर दिया जाएगा।

पोस्टग्रेएसक्यूएल इनहेरिटेंस के बारे में महत्वपूर्ण तथ्य और चेतावनियां

चाइल्ड टेबल इनहेरिट करती है:

  • पूर्ण बाधाएं नहीं
  • बाधाओं की जांच करें

चाइल्ड टेबल इनहेरिट नहीं करती:

  • प्राथमिक कुंजी बाधाएं
  • अद्वितीय बाधाएं
  • विदेशी प्रमुख बाधाएं

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

मूल तालिका में स्कीमा परिवर्तन (वैकल्पिक तालिका के माध्यम से) इस पैरेंट तालिका के नीचे मौजूद पदानुक्रम में प्रचारित किए जाते हैं। और यह PostgreSQL में इनहेरिटेंस की अच्छी विशेषताओं में से एक है।

सुरक्षा और सुरक्षा नीतियां (आरएलएस) हमारे द्वारा उपयोग की जाने वाली वास्तविक तालिका के आधार पर तय की जाती हैं। अगर हम पैरेंट टेबल का इस्तेमाल करते हैं तो उस टेबल की सिक्योरिटी और आरएलएस का इस्तेमाल किया जाएगा। यह निहित है कि पैरेंट टेबल पर विशेषाधिकार देने से चाइल्ड टेबल को भी अनुमति मिलती है, लेकिन केवल जब पैरेंट टेबल के माध्यम से एक्सेस किया जाता है। चाइल्ड टेबल को सीधे एक्सेस करने के लिए, हमें सीधे चाइल्ड टेबल पर स्पष्ट GRANT देना होगा, पैरेंट टेबल पर विशेषाधिकार पर्याप्त नहीं होगा। आरएलएस के लिए भी यही सच है।

ट्रिगर्स की फायरिंग के संबंध में, स्टेटमेंट-लेवल ट्रिगर्स स्टेटमेंट की नामित तालिका पर निर्भर करते हैं, जबकि रो-लेवल ट्रिगर्स को उस टेबल के आधार पर सक्रिय किया जाएगा, जिससे वास्तविक पंक्ति संबंधित है (इसलिए यह चाइल्ड टेबल हो सकती है)।

ध्यान देने योग्य बातें:

  • अधिकांश कमांड पूरे पदानुक्रम पर काम करते हैं और केवल अंकन का समर्थन करते हैं। हालाँकि, कुछ निम्न स्तर के आदेश (REINDEX, VACUUM, आदि) केवल कमांड द्वारा नामित भौतिक तालिकाओं पर काम करते हैं। संदेह की स्थिति में हर बार दस्तावेज़ को पढ़ना सुनिश्चित करें।
  • विदेशी कुंजी बाधाएं (संदर्भ पक्ष पर होने वाली मूल तालिका) विरासत में नहीं मिली हैं। पदानुक्रम के सभी बच्चों की तालिकाओं में समान FK बाधा निर्दिष्ट करके इसे आसानी से हल किया जाता है।
  • इस बिंदु तक (PostgreSQL 10), तालिकाओं के समूह पर वैश्विक UNIQUE INDEX (प्राथमिक कुंजियाँ या UNIQUE बाधाएँ) रखने का कोई तरीका नहीं है। इसके परिणामस्वरूप:
    • प्राथमिक कुंजी और अद्वितीय बाधाएं विरासत में नहीं मिली हैं, और पदानुक्रम के सभी सदस्यों में एक स्तंभ पर विशिष्टता लागू करने का कोई आसान तरीका नहीं है
    • जब पैरेंट टेबल एक FOREIGN KEY बाधा के संदर्भित पक्ष पर होता है, तो चेक केवल मूल तालिका से संबंधित पंक्तियों पर कॉलम के मानों के लिए किया जाता है, न कि किसी भी बच्चे की टेबल से।

अंतिम सीमा एक गंभीर है। आधिकारिक डॉक्स के अनुसार इसके लिए कोई अच्छा समाधान नहीं है। हालांकि, एफके और विशिष्टता किसी भी गंभीर डेटाबेस डिजाइन के लिए मौलिक हैं। हम इससे निपटने का कोई तरीका खोजेंगे।

आज श्वेतपत्र डाउनलोड करें क्लस्टरकंट्रोल के साथ पोस्टग्रेएसक्यूएल प्रबंधन और स्वचालन इस बारे में जानें कि पोस्टग्रेएसक्यूएल को तैनात करने, मॉनिटर करने, प्रबंधित करने और स्केल करने के लिए आपको क्या जानना चाहिए। श्वेतपत्र डाउनलोड करें

अभ्यास में विरासत

इस खंड में, हम सादे तालिकाओं, प्राथमिक कुंजी/अद्वितीय और विदेशी कुंजी बाधाओं के साथ एक क्लासिक डिजाइन को विरासत के आधार पर एक बहु-किरायेदार डिजाइन में बदल देंगे और हम (पिछले अनुभाग के अनुसार अपेक्षित) समस्याओं को हल करने का प्रयास करेंगे। चेहरा। आइए हम उसी किराये के व्यवसाय पर विचार करें जिसका हमने पिछले ब्लॉग में उदाहरण के रूप में उपयोग किया था और आइए कल्पना करें कि शुरुआत में व्यवसाय केवल कार किराए पर लेता है (कोई नाव या अन्य प्रकार के वाहन नहीं)। आइए निम्नलिखित स्कीमा पर विचार करें, कंपनी के वाहनों और उन वाहनों पर सेवा इतिहास के साथ:

create table vehicle (id SERIAL PRIMARY KEY, plate_no text NOT NULL, maker TEXT NOT NULL, model TEXT NOT NULL,vin text not null);
create table vehicle_service(id SERIAL PRIMARY KEY, vehicleid INT NOT NULL REFERENCES vehicle(id), service TEXT NOT NULL, date_performed DATE NOT NULL DEFAULT now(), cost real not null);
rentaldb=# insert into vehicle (plate_no,maker,model,vin) VALUES ('INI888','Hyundai','i20','HH999');
rentaldb=# insert into vehicle_service (vehicleid,service,cost) VALUES(1,'engine oil change/filters',50);

अब आइए कल्पना करें कि सिस्टम उत्पादन में है, और फिर कंपनी एक दूसरी कंपनी का अधिग्रहण करती है जो नाव किराए पर लेती है और उन्हें सिस्टम में एकीकृत करना होता है, जहां तक ​​​​ऑपरेशन जाता है, दोनों कंपनियों को स्वतंत्र रूप से संचालित करने के लिए, लेकिन एकीकृत तरीके से शीर्ष एमजीएमटी द्वारा उपयोग करें। इसके अलावा, आइए कल्पना करें कि Vehicle_service डेटा को विभाजित नहीं किया जाना चाहिए क्योंकि सभी पंक्तियाँ दोनों कंपनियों को दिखाई देनी चाहिए। तो हम जो खोज रहे हैं वह वाहन टेबल पर विरासत के आधार पर एक बहु-किरायेदारी समाधान प्रदान करता है। सबसे पहले, हमें कारों के लिए एक नया स्कीमा बनाना चाहिए, (पुराना व्यवसाय), और एक नावों के लिए और फिर मौजूदा डेटा को कारों में माइग्रेट करना चाहिए। वाहन:

rentaldb=# create schema cars;
rentaldb=# create table cars.vehicle (CONSTRAINT vehicle_pkey PRIMARY KEY(id) ) INHERITS (public.vehicle);
rentaldb=# \d cars.vehicle
                              Table "cars.vehicle"
  Column  |  Type   | Collation | Nullable |               Default               
----------+---------+-----------+----------+-------------------------------------
 id       | integer |           | not null | nextval('vehicle_id_seq'::regclass)
 plate_no | text    |           | not null |
 maker    | text    |           | not null |
 model    | text    |           | not null |
 vin      | text    |           | not null |
Indexes:
    "vehicle_pkey" PRIMARY KEY, btree (id)
Inherits: vehicle
rentaldb=# create schema boats;
rentaldb=# create table boats.vehicle (CONSTRAINT vehicle_pkey PRIMARY KEY(id) ) INHERITS (public.vehicle);
rentaldb=# \d boats.vehicle
                              Table "boats.vehicle"
  Column  |  Type   | Collation | Nullable |               Default               
----------+---------+-----------+----------+-------------------------------------
 id       | integer |           | not null | nextval('vehicle_id_seq'::regclass)
 plate_no | text    |           | not null |
 maker    | text    |           | not null |
 model    | text    |           | not null |
 vin      | text    |           | not null |
Indexes:
    "vehicle_pkey" PRIMARY KEY, btree (id)
Inherits: vehicle

हम ध्यान दें कि नई तालिकाएँ id . कॉलम के लिए समान डिफ़ॉल्ट मान साझा करती हैं (समान क्रम) मूल तालिका के रूप में। हालांकि यह पिछले खंड में बताई गई वैश्विक विशिष्टता समस्या के समाधान से बहुत दूर है, यह एक समाधान है, बशर्ते कि किसी भी स्पष्ट मूल्य का कभी भी इन्सर्ट या अपडेट के लिए उपयोग नहीं किया जाएगा। अगर सभी बच्चों के टेबल (cars.vehicle और boats.vehicle) को ऊपर के रूप में परिभाषित किया गया है, और हम कभी भी आईडी में स्पष्ट हेरफेर नहीं करते हैं, तो हम सुरक्षित रहेंगे।

चूंकि हम केवल सार्वजनिक वाहन_सेवा तालिका रखेंगे और यह बच्चों की तालिकाओं की पंक्तियों को संदर्भित करेगा, हमें FK बाधा को छोड़ना होगा:

rentaldb=# alter table vehicle_service drop CONSTRAINT vehicle_service_vehicleid_fkey ;

लेकिन चूंकि हमें अपने डेटाबेस में समान स्थिरता बनाए रखने की आवश्यकता है, इसलिए हमें इसके लिए एक समाधान खोजना होगा। हम ट्रिगर्स का उपयोग करके इस बाधा को लागू करेंगे। हमें Vehicle_service में एक ट्रिगर जोड़ने की आवश्यकता है जो यह जांचता है कि प्रत्येक INSERT या UPDATE के लिए वाहन सार्वजनिक.वाहन* पदानुक्रम में कहीं एक वैध पंक्ति की ओर इशारा करता है, और इस पदानुक्रम की प्रत्येक तालिका पर एक ट्रिगर जो यह जाँचता है कि प्रत्येक DELETE या अद्यतन आईडी पर, वाहन_सेवा में कोई पंक्ति मौजूद नहीं है जो पुराने मूल्य की ओर इशारा करती है। (वाहन द्वारा नोट* नोटेशन PostgreSQL का अर्थ यह और सभी बच्चों की टेबल है)

CREATE OR REPLACE FUNCTION public.vehicle_service_fk_to_vehicle() RETURNS TRIGGER
        LANGUAGE plpgsql
AS $$
DECLARE
tmp INTEGER;
BEGIN
        IF (TG_OP = 'DELETE') THEN
          RAISE EXCEPTION 'TRIGGER : % called on unsuported op : %',TG_NAME, TG_OP;
        END IF;
        SELECT vh.id INTO tmp FROM public.vehicle vh WHERE vh.id=NEW.vehicleid;
        IF NOT FOUND THEN
          RAISE EXCEPTION '%''d % (id=%) with NEW.vehicleid (%) does not match any vehicle ',TG_OP, TG_TABLE_NAME, NEW.id, NEW.vehicleid USING ERRCODE = 'foreign_key_violation';
        END IF;
        RETURN NEW;
END
$$
;
CREATE CONSTRAINT TRIGGER vehicle_service_fk_to_vehicle_tg AFTER INSERT OR UPDATE ON public.vehicle_service FROM public.vehicle DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE public.vehicle_service_fk_to_vehicle();

अगर हम कॉलम व्हीकलिड के लिए एक मान के साथ अपडेट या डालने का प्रयास करते हैं जो वाहन में मौजूद नहीं है* तो हमें एक त्रुटि मिलेगी:

rentaldb=# insert into vehicle_service (vehicleid,service,cost) VALUES(2,'engine oil change/filters',50);
ERROR:  INSERT'd vehicle_service (id=2) with NEW.vehicleid (2) does not match any vehicle
CONTEXT:  PL/pgSQL function vehicle_service_fk_to_vehicle() line 10 at RAISE

अब यदि हम पदानुक्रम में किसी तालिका में एक पंक्ति सम्मिलित करते हैं उदा। bots.vehicle (जो सामान्य रूप से id=2 लेगा) और पुनः प्रयास करें:

rentaldb=# insert into boats.vehicle (maker, model,plate_no,vin) VALUES('Zodiac','xx','INI000','ZZ20011');
rentaldb=# select * from vehicle;
 id | plate_no |  maker  | model |   vin   
----+----------+---------+-------+---------
  1 | INI888   | Hyundai | i20   | HH999
  2 | INI000   | Zodiac  | xx    | ZZ20011
(2 rows)
rentaldb=# insert into vehicle_service (vehicleid,service,cost) VALUES(2,'engine oil change/filters',50);

फिर पिछला INSERT अब सफल होता है। अब हमें दूसरी तरफ भी इस एफके संबंध की रक्षा करनी चाहिए, हमें यह सुनिश्चित करना चाहिए कि पदानुक्रम में किसी भी तालिका पर किसी भी अद्यतन/हटाने की अनुमति नहीं है यदि हटाई जाने वाली पंक्ति (या अद्यतन) को वाहन_सेवा द्वारा संदर्भित किया गया है:

CREATE OR REPLACE FUNCTION public.vehicle_fk_from_vehicle_service() RETURNS TRIGGER
        LANGUAGE plpgsql
AS $$
DECLARE
tmp INTEGER;
BEGIN
        IF (TG_OP = 'INSERT') THEN
          RAISE EXCEPTION 'TRIGGER : % called on unsuported op : %',TG_NAME, TG_OP;
        END IF;
        IF (TG_OP = 'DELETE' OR OLD.id <> NEW.id) THEN
          SELECT vhs.id INTO tmp FROM vehicle_service vhs WHERE vhs.vehicleid=OLD.id;
          IF FOUND THEN
            RAISE EXCEPTION '%''d % (OLD id=%) matches existing vehicle_service with id=%',TG_OP, TG_TABLE_NAME, OLD.id,tmp USING ERRCODE = 'foreign_key_violation';
          END IF;
        END IF;
        IF (TG_OP = 'UPDATE') THEN
                RETURN NEW;
        ELSE
                RETURN OLD;
        END IF;
END
$$
;
CREATE CONSTRAINT TRIGGER vehicle_fk_from_vehicle_service AFTER DELETE OR UPDATE
ON public.vehicle FROM vehicle_service DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE vehicle_fk_from_vehicle_service();
CREATE CONSTRAINT TRIGGER vehicle_fk_from_vehicle_service AFTER DELETE OR UPDATE
ON cars.vehicle FROM vehicle_service DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE vehicle_fk_from_vehicle_service();
CREATE CONSTRAINT TRIGGER vehicle_fk_from_vehicle_service AFTER DELETE OR UPDATE
ON boats.vehicle FROM vehicle_service DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE vehicle_fk_from_vehicle_service();

आइए इसे आजमाएं:

rentaldb=# delete from vehicle where id=2;
ERROR:  DELETE'd vehicle (OLD id=2) matches existing vehicle_service with id=3
CONTEXT:  PL/pgSQL function vehicle_fk_from_vehicle_service() line 11 at RAISE

अब हमें public.vehicle में मौजूद मौजूदा डेटा को car.vehicle में ले जाने की आवश्यकता है।

rentaldb=# begin ;
rentaldb=# set constraints ALL deferred ;
rentaldb=# set session_replication_role TO replica;
rentaldb=# insert into cars.vehicle select * from only public.vehicle;
rentaldb=# delete from only public.vehicle;
rentaldb=# commit ;

सेशन_रेप्लिकेशन_रोल टू रेप्लिका सेट करना सामान्य ट्रिगर्स को सक्रिय होने से रोकता है। ध्यान दें कि, डेटा को स्थानांतरित करने के बाद, हम सम्मिलन स्वीकार करने की मूल तालिका (public.vehicle) को पूरी तरह से अक्षम करना चाह सकते हैं (संभवतः एक नियम के माध्यम से)। इस मामले में, OO सादृश्य में, हम public.vehicle को एक अमूर्त वर्ग के रूप में मानेंगे, अर्थात बिना पंक्तियों (उदाहरणों) के। बहु-किरायेदारी के लिए इस डिज़ाइन का उपयोग करना स्वाभाविक लगता है क्योंकि हल की जाने वाली समस्या विरासत के लिए एक क्लासिक उपयोग का मामला है, हालाँकि, जिन समस्याओं का हमने सामना किया, वे तुच्छ नहीं हैं। हैकर्स समुदाय द्वारा इस पर चर्चा की गई है, और हम भविष्य में सुधार की आशा करते हैं।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL में क्वेरी ऑप्टिमाइज़ेशन। मूल बातें समझाएं - भाग 3

  2. psql \copy का उपयोग करके टाइमस्टैम्प कॉलम (dd.mm.yyyy hh.mm.ss) के साथ .csv आयात करना

  3. PostgreSQL में दोष सहिष्णुता का विकास

  4. Postgres - 2 ARRAYs के प्रतिच्छेदन को वापस करने का कार्य?

  5. सभी तालिका नामों को सूचीबद्ध करने के लिए PostgreSQL क्वेरी?