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

माता-पिता को हटा दें यदि यह किसी अन्य बच्चे द्वारा संदर्भित नहीं है

PostgreSQL में 9.1 या बाद के संस्करण आप इसे डेटा-संशोधित CTE . का उपयोग करके एकल कथन के साथ कर सकते हैं . यह आमतौर पर कम त्रुटि प्रवण होता है। यह छोटा करता है दो DELETEs के बीच की समय सीमा जिसमें एक दौड़ की स्थिति समवर्ती संचालन के साथ आश्चर्यजनक परिणाम हो सकते हैं:

WITH del_child AS (
    DELETE FROM child
    WHERE  child_id = 1
    RETURNING parent_id, child_id
    )
DELETE FROM parent p
USING  del_child x
WHERE  p.parent_id = x.parent_id
AND    NOT EXISTS (
   SELECT 1
   FROM   child c
   WHERE  c.parent_id = x.parent_id
   AND    c.child_id <> x.child_id   -- !
   );

एसक्यूएल फिडल.

बच्चे को किसी भी मामले में हटा दिया जाता है। मैं मैनुअल उद्धृत करता हूं:

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

WITH में डेटा-संशोधित विवरण ठीक एक बार निष्पादित होते हैं, औरहमेशा पूर्ण होने के लिए , इस बात से स्वतंत्र रूप से कि क्या प्राथमिक क्वेरी उनके आउटपुट के सभी (या वास्तव में कोई भी) पढ़ती है। ध्यान दें कि यह SELECT . के नियम से अलग है में WITH :जैसा कि पिछले अनुभाग में बताया गया है, SELECT . का निष्पादन केवल तब तक ले जाया जाता है जब तक प्राथमिक क्वेरी इसके आउटपुट की मांग करती है।

पैरेंट को केवल तभी हटाया जाता है जब उसके पास कोई अन्य न हो बच्चे।
आखिरी शर्त पर ध्यान दें। किसी की अपेक्षा के विपरीत, यह आवश्यक है, क्योंकि:

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

उप-विवरण WITH . में हैं समवर्ती रूप से निष्पादित किए जाते हैं एक दूसरे के साथ और मुख्य प्रश्न के साथ। इसलिए, WITH में डेटा-संशोधित कथनों का उपयोग करते समय , जिस क्रम में निर्दिष्ट अद्यतन वास्तव में होते हैं वह अप्रत्याशित है। सभी कथनों को उसी स्नैपशॉट के साथ क्रियान्वित किया जाता है (अध्याय 13 देखें), इसलिए वे लक्ष्य तालिकाओं पर एक-दूसरे के प्रभावों को "देख" नहीं सकते हैं।

बोल्ड जोर मेरा।
मैंने कॉलम नाम का उपयोग किया parent_id गैर-वर्णनात्मक id . के स्थान पर ।

दौड़ की स्थिति को हटा दें

संभावित दौड़ स्थितियों को समाप्त करने के लिए जिनका मैंने ऊपर उल्लेख किया है पूरी तरह से , पैरेंट रो को लॉक करें पहले . बेशक, सभी इसी तरह के संचालन को इसे काम करने के लिए उसी प्रक्रिया का पालन करना चाहिए।

WITH lock_parent AS (
   SELECT p.parent_id, c.child_id
   FROM   child  c
   JOIN   parent p ON p.parent_id = c.parent_id
   WHERE  c.child_id = 12              -- provide child_id here once
   FOR    NO KEY UPDATE                -- locks parent row.
   )
 , del_child AS (
   DELETE FROM child c
   USING  lock_parent l
   WHERE  c.child_id = l.child_id
   )
DELETE FROM parent p
USING  lock_parent l
WHERE  p.parent_id = l.parent_id
AND    NOT EXISTS (
   SELECT 1
   FROM   child c
   WHERE  c.parent_id = l.parent_id
   AND    c.child_id <> l.child_id   -- !
   );

इस तरह केवल एक एक ही समय में लेन-देन एक ही माता-पिता को लॉक कर सकता है। तो ऐसा नहीं हो सकता है कि कई लेन-देन एक ही माता-पिता के बच्चों को हटा दें, फिर भी अन्य बच्चों को देखें और माता-पिता को छोड़ दें, जबकि सभी बच्चे बाद में चले गए हैं। (गैर-कुंजी कॉलम पर अपडेट की अभी भी अनुमति है FOR NO KEY UPDATE ।)

यदि ऐसे मामले कभी नहीं होते हैं या आप इसके साथ (शायद ही कभी) रह सकते हैं - पहली क्वेरी सस्ती है। नहीं तो यह सुरक्षित रास्ता है।

FOR NO KEY UPDATE पोस्टग्रेज 9.4 के साथ पेश किया गया था। मैनुअल में विवरण। पुराने संस्करणों में मजबूत लॉक का उपयोग करें FOR UPDATE इसके बजाय।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Django कनेक्शन निरस्त त्रुटि:[WinError 10053] एक स्थापित कनेक्शन आपके होस्ट मशीन में सॉफ़्टवेयर द्वारा निरस्त कर दिया गया था

  2. कैसे अजगर के साथ Postgresql में JSONB सम्मिलित करने के लिए?

  3. डॉकटर-कंपोज़ अप के बाद पोस्टग्रेज डंप लोड करें

  4. पोस्टग्रेएसक्यूएल विवरण तालिका

  5. कॉलम प्रकार को रेल में लंबे समय तक स्ट्रिंग में बदलना