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

SQLAlchemy में जटिल विदेशी कुंजी बाधा

आप इसे बिना गंदी चाल के लागू कर सकते हैं . बस विदेशी कुंजी का विस्तार करें variable_id . को शामिल करने के लिए चुने गए विकल्प का संदर्भ देना choice_id . के अलावा ।

यहां एक कामकाजी डेमो है। अस्थायी टेबल, ताकि आप इसके साथ आसानी से खेल सकें:

CREATE TABLE systemvariables (
  variable_id int PRIMARY KEY
, choice_id   int
, variable    text
);
   
INSERT INTO systemvariables(variable_id, variable) VALUES
  (1, 'var1')
, (2, 'var2')
, (3, 'var3')
;

CREATE TABLE variableoptions (
  option_id   int PRIMARY KEY
, variable_id int REFERENCES systemvariables ON UPDATE CASCADE ON DELETE CASCADE
, option      text
, UNIQUE (option_id, variable_id)  -- needed for the FK
);

ALTER TABLE systemvariables
  ADD CONSTRAINT systemvariables_choice_id_fk
  FOREIGN KEY (choice_id, variable_id) REFERENCES variableoptions(option_id, variable_id);

INSERT INTO variableoptions  VALUES
  (1, 'var1_op1', 1)
, (2, 'var1_op2', 1)
, (3, 'var1_op3', 1)
, (4, 'var2_op1', 2)
, (5, 'var2_op2', 2)
, (6, 'var3_op1', 3)
;

संबद्ध विकल्प चुनने की अनुमति है:

UPDATE systemvariables SET choice_id = 2 WHERE variable_id = 1;
UPDATE systemvariables SET choice_id = 5 WHERE variable_id = 2;
UPDATE systemvariables SET choice_id = 6 WHERE variable_id = 3;

लेकिन कोई आउट ऑफ लाइन नहीं है:

UPDATE systemvariables SET choice_id = 7 WHERE variable_id = 3;
UPDATE systemvariables SET choice_id = 4 WHERE variable_id = 1;
ERROR:  insert or update on table "systemvariables" violates foreign key constraint "systemvariables_choice_id_fk"
DETAIL: Key (choice_id,variable_id)=(4,1) is not present in table "variableoptions".

ठीक वही जो आप चाहते थे।

सभी प्रमुख कॉलम NOT NULL

मुझे लगता है कि मुझे इस बाद के उत्तर में एक बेहतर समाधान मिला:

  • परस्पर निर्भर निवेशन से कैसे निपटें

टिप्पणियों में @ypercube के प्रश्न को संबोधित करते हुए, अज्ञात संबद्धता वाली प्रविष्टियों से बचने के लिए सभी प्रमुख कॉलम बनाएं NOT NULL , विदेशी कुंजी सहित।

परिपत्र निर्भरता सामान्य रूप से असंभव बना देगी। यह शास्त्रीय चिकन-अंडा है समस्या:दोनों में से एक को दूसरे को जन्म देने के लिए पहले वहां होना चाहिए। लेकिन प्रकृति ने इसके चारों ओर एक रास्ता खोज लिया, और पोस्टग्रेज ने भी ऐसा ही किया:स्थगित विदेशी कुंजी बाधाएं

CREATE TABLE systemvariables (
  variable_id int PRIMARY KEY
, variable    text
, choice_id   int NOT NULL
);

CREATE TABLE variableoptions (
  option_id   int PRIMARY KEY
, option      text
, variable_id int NOT NULL REFERENCES systemvariables
     ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
, UNIQUE (option_id, variable_id) -- needed for the foreign key
);

ALTER TABLE systemvariables
ADD CONSTRAINT systemvariables_choice_id_fk FOREIGN KEY (choice_id, variable_id)
   REFERENCES variableoptions(option_id, variable_id) DEFERRABLE INITIALLY DEFERRED; -- no CASCADING here!

नया चर और संबद्ध विकल्पों को एक ही लेन-देन में सम्मिलित करना होगा:

BEGIN;

INSERT INTO systemvariables (variable_id, variable, choice_id)
VALUES
  (1, 'var1', 2)
, (2, 'var2', 5)
, (3, 'var3', 6);

INSERT INTO variableoptions (option_id, option, variable_id)
VALUES
  (1, 'var1_op1', 1)
, (2, 'var1_op2', 1)
, (3, 'var1_op3', 1)
, (4, 'var2_op1', 2)
, (5, 'var2_op2', 2)
, (6, 'var3_op1', 3);

END;

NOT NULL प्रतिबंध को स्थगित नहीं किया जा सकता है, इसे तुरंत लागू किया जाता है। लेकिन विदेशी कुंजी बाधा कर सकते हैं , क्योंकि हमने इसे इस तरह परिभाषित किया है। लेन-देन के अंत में इसकी जाँच की जाती है, जिससे चिकन-अंडे की समस्या से बचा जा सकता है।

इसमें संपादित परिदृश्य, दोनों विदेशी कुंजियां स्थगित हैं . आप मनमाने क्रम में चर और विकल्प दर्ज कर सकते हैं।
यदि आप एक कथन में दोनों तालिका में संबंधित प्रविष्टियां दर्ज करते हैं, तो आप इसे सादे गैर-आस्थगित FK बाधा के साथ भी काम कर सकते हैं। लिंक किए गए उत्तर में विस्तृत रूप से सीटीई का उपयोग करना।

आपने देखा होगा कि पहली विदेशी कुंजी बाधा में कोई CASCADE नहीं है संशोधक (variableoptions.variable_id . में परिवर्तन की अनुमति देने का कोई मतलब नहीं होगा वापस कैस्केड करने के लिए।

दूसरी ओर, दूसरी विदेशी कुंजी में CASCADE . होता है संशोधक और परिभाषित किया गया है DEFERRABLE फिर भी। यह कुछ सीमाएँ रखता है। मैनुअल:

<ब्लॉकक्वॉट>

NO ACTION . के अलावा अन्य रेफ़रेंशियल कार्रवाइयां चेक को आस्थगित नहीं किया जा सकता, भले ही बाधा को आस्थगित घोषित कर दिया गया हो।

NO ACTION डिफ़ॉल्ट है।

तो, INSERT . पर संदर्भात्मक अखंडता जांच आस्थगित हैं, लेकिन घोषित व्यापक कार्रवाई DELETE . पर और UPDATE नहीं हैं। PostgreSQL 9.0 या बाद के संस्करण में निम्नलिखित की अनुमति नहीं है क्योंकि प्रत्येक कथन के बाद प्रतिबंध लागू होते हैं:

UPDATE option SET var_id = 4 WHERE var_id = 5;
DELETE FROM var WHERE var_id = 5;

विवरण:

  • प्रारंभिक रूप से तत्काल परिभाषित बाधा अभी भी स्थगित है?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. मौजूदा auth.User डेटा को नए Django 1.5 कस्टम उपयोगकर्ता मॉडल में माइग्रेट करना?

  2. PostgreSQL में current_time कैसे काम करता है

  3. PostgreSQL में माध्यिका की गणना कैसे करें

  4. यदि कोई मेल नहीं खाता है तो पहले रिकॉर्ड का चयन करें

  5. क्या किसी भी लेनदेन में डेटाबेस को छोड़ना नहीं है?