सवाल पुराना है, लेकिन यहां सुझाए गए सुझावों को लागू करने का प्रयास करने के बाद हमें dba.SE पर एक हताश उपयोगकर्ता से एक नया प्रश्न मिला। वहां पर अधिक विवरण और स्पष्टीकरण के साथ उत्तर खोजें :
वर्तमान में स्वीकृत उत्तर ज्यादातर मामलों में विफल हो जाएगा ।
-
आमतौर पर, आपके पास
PRIMARY KEY
होता है याUNIQUE
एकid
. पर प्रतिबंध कॉलम, जो किNOT DEFERRABLE
है डिफ़ॉल्ट रूप से। (ओपी मेंreferences and constraints
.) प्रत्येक पंक्ति के बाद इस तरह की बाधाओं की जाँच की जाती है, इसलिए आपको अद्वितीय उल्लंघन होने की सबसे अधिक संभावना है कोशिश कर रही त्रुटियां। विवरण: -
आमतौर पर, कोई व्यक्ति मूल पंक्तियों के क्रम को बनाए रखना चाहता है अंतराल को बंद करते समय। लेकिन पंक्तियों को अपडेट करने का क्रम मनमाना . है , मनमानी संख्या के लिए अग्रणी। प्रदर्शित उदाहरण मूल अनुक्रम को बनाए रखने के लिए लगता है क्योंकि भौतिक भंडारण अभी भी वांछित क्रम के साथ मेल खाता है (बस एक पल पहले वांछित क्रम में पंक्तियों को सम्मिलित किया गया है), जो वास्तविक दुनिया के अनुप्रयोगों में लगभग कभी नहीं होता है और पूरी तरह से अविश्वसनीय होता है।
मामला पहले की तुलना में कहीं अधिक जटिल है। एक समाधान (दूसरों के बीच) यदि आप अस्थायी रूप से PK / UNIQUE बाधा (और संबंधित FK बाधाओं) को दूर करने का जोखिम उठा सकते हैं:
BEGIN;
LOCK tbl;
-- remove all FK constraints to the column
ALTER TABLE tbl DROP CONSTRAINT tbl_pkey; -- remove PK
-- for the simple case without FK references - or see below:
UPDATE tbl t -- intermediate unique violations are ignored now
SET id = t1.new_id
FROM (SELECT id, row_number() OVER (ORDER BY id) AS new_id FROM tbl) t1
WHERE t.id = t1.id;
-- Update referencing value in FK columns at the same time (if any)
SELECT setval('tbl_id_seq', max(id)) FROM tbl; -- reset sequence
ALTER TABLE tbl ADD CONSTRAINT tbl_pkey PRIMARY KEY(id); -- add PK back
-- add all FK constraints to the column back
COMMIT;
यह भी बहुत है बड़ी तालिकाओं के लिए तेज़, क्योंकि प्रत्येक पंक्ति के लिए PK (और FK) बाधाओं की जाँच करने पर बाधाओं को हटाने और इसे (उन्हें) वापस जोड़ने की तुलना में बहुत अधिक खर्च होता है।
यदि tbl.id
. को संदर्भित करने वाली अन्य तालिकाओं में FK कॉलम हैं , डेटा-संशोधित सीटीई उन सभी को अपडेट करने के लिए।
तालिका के लिए उदाहरण fk_tbl
और एक FK कॉलम fk_id
:
WITH u1 AS (
UPDATE tbl t
SET id = t1.new_id
FROM (SELECT id, row_number() OVER (ORDER BY id) AS new_id FROM tbl) t1
WHERE t.id = t1.id
RETURNING t.id, t1.new_id -- return old and new ID
)
UPDATE fk_tbl f
SET fk_id = u1.new_id -- set to new ID
FROM u1
WHERE f.fk_id = u1.id; -- match on old ID
dba.SE पर संदर्भित उत्तर में अधिक ।