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

केवल SQL का उपयोग करके पूर्व-अद्यतन स्तंभ मान लौटाएं

समस्या

मैनुअल बताता है:

<ब्लॉककोट>

वैकल्पिक RETURNING खंड UPDATE का कारण बनता है वास्तव में अद्यतन की गई प्रत्येक पंक्ति के आधार पर गणना और वापसी मूल्य। FROM . में उल्लिखित तालिका के स्तंभों और/या अन्य तालिकाओं के स्तंभों का उपयोग करने वाला कोई व्यंजक , गणना की जा सकती है। तालिका के कॉलम के नए (अपडेट के बाद) मानों का उपयोग किया जाता है . RETURNING . का सिंटैक्स सूची SELECT . की आउटपुट सूची के समान है ।

बोल्ड जोर मेरा। RETURNING . में पुरानी पंक्ति तक पहुंचने का कोई तरीका नहीं है खंड। आप इस प्रतिबंध के आसपास एक ट्रिगर या एक अलग SELECT . के साथ काम कर सकते हैं पहले UPDATE जैसा कि टिप्पणी की गई थी, लेन-देन में लिपटा हुआ या CTE में लिपटा हुआ था।

हालांकि, आप जो हासिल करने की कोशिश कर रहे हैं वह बिल्कुल ठीक काम करता है यदि आप FROM . में तालिका के किसी अन्य उदाहरण में शामिल होते हैं खंड:

समवर्ती लेखन के बिना समाधान

UPDATE tbl x
SET    tbl_id = 23
     , name = 'New Guy'
FROM   tbl y                -- using the FROM clause
WHERE  x.tbl_id = y.tbl_id  -- must be UNIQUE NOT NULL
AND    x.tbl_id = 3
RETURNING y.tbl_id AS old_id, y.name AS old_name
        , x.tbl_id          , x.name;

रिटर्न:

 old_id | old_name | tbl_id |  name
--------+----------+--------+---------
  3     | Old Guy  | 23     | New Guy

स्व-जुड़ने के लिए उपयोग किया जाने वाला कॉलम UNIQUE NOT NULL . होना चाहिए . सरल उदाहरण में, WHERE शर्त एक ही कॉलम पर है tbl_id , लेकिन यह सिर्फ संयोग है। किसी भी . के लिए काम करता है शर्तें।

मैंने इसका परीक्षण 8.4 से 13 तक PostgreSQL संस्करणों के साथ किया।

यह INSERT . के लिए अलग है :

  • इसमें सम्मिलित करें ... चयन से ... रिटर्निंग आईडी मैपिंग

समवर्ती लेखन भार वाले समाधान

एक ही पंक्तियों पर समवर्ती लेखन संचालन के साथ दौड़ की स्थिति से बचने के कई तरीके हैं। (ध्यान दें कि असंबंधित पंक्तियों पर समवर्ती लेखन संचालन कोई समस्या नहीं है।) सरल, धीमी और सुनिश्चित (लेकिन महंगी) विधि SERIALIZABLE के साथ लेन-देन को चलाने के लिए है अलगाव स्तर:

BEGIN ISOLATION LEVEL SERIALIZABLE;
UPDATE ... ;
COMMIT;

लेकिन यह शायद अधिक है। और आपको क्रमांकन विफल होने की स्थिति में ऑपरेशन को दोहराने के लिए तैयार रहने की आवश्यकता है।

सरल और तेज़ (और समवर्ती लेखन भार के साथ उतना ही विश्वसनीय) एक . पर एक स्पष्ट लॉक है अद्यतन की जाने वाली पंक्ति:

UPDATE tbl x
SET    tbl_id = 24
     , name = 'New Gal'
FROM  (SELECT tbl_id, name FROM tbl WHERE tbl_id = 4 FOR UPDATE) y 
WHERE  x.tbl_id = y.tbl_id
RETURNING y.tbl_id AS old_id, y.name AS old_name
        , x.tbl_id          , x.name;

ध्यान दें कि कैसे WHERE शर्त को सबक्वेरी में ले जाया गया (फिर से, कुछ भी हो सकता है ), और केवल सेल्फ-जॉइन (UNIQUE NOT NULL . पर) कॉलम (एस)) बाहरी क्वेरी में रहता है। यह गारंटी देता है कि केवल पंक्तियों को आंतरिक SELECT . द्वारा लॉक किया गया है संसाधित होते हैं। WHERE स्थितियाँ एक क्षण बाद पंक्तियों के किसी भिन्न समूह में हल हो सकती हैं।

देखें:

  • परमाणु अद्यतन .. पोस्टग्रेज में चुनें

db<>यहां बेला करें
पुराना sqlfiddle



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. क्या दशमलव डेटा प्रकारों (MySQL / Postgres) का उपयोग करके कोई प्रदर्शन हिट है

  2. त्रुटि:संबंध स्थान मौजूद नहीं है हरोकू डीबी आयात

  3. PostgreSQL में वर्तमान समय (समय क्षेत्र के बिना) कैसे प्राप्त करें

  4. एक ही क्वेरी में एकाधिक array_agg () कॉल

  5. PostgreSQL अपग्रेड को खोलना