मैं Postgresql डेटाबेस में एक कॉलम कैसे जोड़ सकता हूं जो नल की अनुमति नहीं देता है?


243

मैं निम्नलिखित क्वेरी (इंटरनेट के लिए स्वच्छता) का उपयोग करके अपने Postgresql डेटाबेस में एक नया, "NOT NULL" कॉलम जोड़ रहा हूं:

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL;

जब भी मैं इस प्रश्न को चलाता हूं, मुझे निम्न त्रुटि संदेश प्राप्त होता है:

ERROR:  column "mycolumn" contains null values

मैं उलझन में हूं। मुझसे कहां गलती हो रही है?

नोट: मैं प्राथमिक रूप से pgAdmin III (1.8.4) का उपयोग कर रहा हूं, लेकिन मुझे वही त्रुटि मिली जब मैंने टर्मिनल से SQL चलाया।

जवाबों:


400

आपको एक डिफ़ॉल्ट मान सेट करना होगा।

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL DEFAULT 'foo';

... some work (set real values as you want)...

ALTER TABLE mytable ALTER COLUMN mycolumn DROP DEFAULT;

1
अच्छा समाधान है। मैं ऑनलाइन किसी कारण के लिए डॉक्स पोस्टग्रेज नहीं कर सका, यह देखने के लिए कि सिंटैक्स क्या होगा।
शाइन ब्राइट

4
@ सीन सही, आप डॉक ऑफ़लाइन पोस्ट करने के लिए उपयोग कर सकते हैं man ALTER_TABLE :)
allan.simon

@ allan.simon मैंने पहले कभी भी PostgreSQL का उपयोग नहीं किया है और मैंने इसे कहीं भी स्थापित नहीं किया है।
सीन ब्राइट

2
स्पष्ट करने के लिए: डिफ़ॉल्ट मान केवल मौजूदा पंक्तियों को अपडेट करने के लिए आवश्यक है, यही कारण है कि इसे तुरंत बाद में गिराया जा सकता है। सभी मौजूदा पंक्तियों को अपडेट कर दिया गया है जब तालिका को बदल दिया गया था (जो कि कुछ समय लग सकता है, जाहिर है)
MSalters

2
यदि आप मौजूदा पंक्तियों के लिए प्रारंभिक मान की गणना करने के लिए किसी अन्य स्तंभ का उपयोग करना चाहते हैं तो यह काम नहीं करेगा। j_random_hacker का उत्तर इसके लिए अनुमति देता है, जो इसे और अधिक मजबूत बनाता है।
jpmc26

82

जैसा कि दूसरों ने देखा है, आपको या तो एक अशक्त स्तंभ बनाना होगा या एक DEFAULT मान प्रदान करना होगा। यदि यह पर्याप्त रूप से लचीला नहीं है (जैसे यदि आपको प्रत्येक पंक्ति के लिए किसी न किसी तरह से नए मूल्य की गणना करने की आवश्यकता है), तो आप इस तथ्य का उपयोग कर सकते हैं कि PostgreSQL में, सभी डीडीएल आदेशों को लेनदेन के अंदर निष्पादित किया जा सकता है:

BEGIN;
ALTER TABLE mytable ADD COLUMN mycolumn character varying(50);
UPDATE mytable SET mycolumn = timeofday();    -- Just a silly example
ALTER TABLE mytable ALTER COLUMN mycolumn SET NOT NULL;
COMMIT;

7
यहां तक ​​कि एक लेन-देन में भी, NULL को तुरंत लागू नहीं किया जाता है, इसलिए पहले कॉलम को जोड़ना होगा, मूल्यों को भरना होगा, फिर NOT NULL को जोड़ना होगा - जैसा कि यह उत्तर देता है। (पोस्टग्रैस 9.6 पर परीक्षण किया गया)
बेनी चेर्नियाव्स्की-पास्किन

48

चूँकि पंक्तियाँ पहले से ही तालिका में मौजूद हैं, ALTERबयान NULLमौजूदा सभी पंक्तियों के लिए नए बनाए गए कॉलम में सम्मिलित करने का प्रयास कर रहा है । आपको कॉलम को अनुमति के रूप में जोड़ना होगा NULL, फिर कॉलम को उन मानों के साथ भरें जिन्हें आप चाहते हैं, और फिर बाद में सेट करें NOT NULL


7
यह कैसे करना है का उदाहरण वास्तव में अच्छा रहा होगा। अन्यथा, ल्यूक का समाधान अधिक पूर्ण और उपयोग के लिए तैयार लगता है।
विक्टर फराजदगी

5

आपको या तो एक डिफ़ॉल्ट को परिभाषित करने की आवश्यकता है, या शॉन जो कहता है और उसे बिना किसी बाधा के जोड़ दें जब तक कि आपने इसे मौजूदा पंक्तियों पर नहीं भरा हो।


2

एक डिफ़ॉल्ट मान निर्दिष्ट करना भी काम करेगा, एक डिफ़ॉल्ट मान उचित है।


2
यह कॉलम को एक डिफ़ॉल्ट मान (चित्रण के लिए) बनाने के लिए संशोधित सिंटैक्स देने के उत्तर को बेहतर करेगा।
हार्डमैथ

1

या, अतिरिक्त स्तंभ के साथ अस्थायी के रूप में एक नई तालिका बनाएं, गैर-अशक्त नए कॉलम को भरने के लिए आवश्यक रूप में हेरफेर करते हुए इस नई तालिका में डेटा की प्रतिलिपि बनाएँ, और फिर दो-चरण नाम परिवर्तन के माध्यम से तालिका को स्वैप करें।

हां, यह अधिक जटिल है, लेकिन अगर आप लाइव टेबल पर एक बड़ा अद्यतन नहीं चाहते हैं, तो आपको इसे इस तरह से करने की आवश्यकता हो सकती है।


3
मैंने आपको -1 नहीं दिया, लेकिन मुझे लगता है कि इसके साथ सूक्ष्म कठिनाइयाँ हो सकती हैं - जैसे मैं शर्त लगा रहा हूं कि मौजूदा सूचकांक, ट्रिगर्स और विचार नाम बदलने के बाद भी मूल तालिका को संदर्भित करना जारी रखेंगे क्योंकि मुझे लगता है कि वे स्टोर करते हैं अपने नाम के बजाय तालिका (जो नहीं बदलती) से छुटकारा।
j_random_hacker 13

1
हां, मुझे कहना चाहिए कि नई तालिका मूल की एक सटीक प्रति होनी चाहिए, जिसमें सूचकांक और ऐसे शामिल हैं। बहुत संक्षिप्त होने के लिए मेरा बुरा। इसका कारण यह है कि एक मेज पर ALTER करने के सूक्ष्म अंतर भी हैं जो जीवित हो सकते हैं, और कभी-कभी आपको इसे चरणबद्ध करने की आवश्यकता होती है।
अल्फा फॉग

उदाहरण के लिए, DEFAULT दृष्टिकोण का उपयोग करते हुए, आप उस डिफ़ॉल्ट मान को प्रत्येक पंक्ति में जोड़ देंगे। यह सुनिश्चित नहीं है कि पोस्टग्रेज ऐसा करते समय टेबल को लॉक कैसे करता है। या, यदि कॉलम ऑर्डर मायने रखता है, तो आप केवल ALTER कमांड के साथ कॉलम नहीं जोड़ सकते।
अल्फा फॉग

पर्याप्त रूप से, उचित तालिका PostgreSQL डॉक्स के अनुसार तालिका को लॉक करती है, हालांकि यदि टेबल वास्तव में लाइव है तो आपके गैर-लेन-देन के दृष्टिकोण में परिवर्तन होने का जोखिम है। इसके अलावा, मैं सुझाव दूंगा कि कोई भी कोड जो कॉलम ऑर्डर पर निर्भर करता है, वह टूट गया है (जो आपके नियंत्रण के बाहर हो सकता है)।
j_random_hacker

2
यह दृष्टिकोण भी विशेष रूप से समस्याग्रस्त है यदि तालिका को विदेशी कुंजी अनुक्रमों द्वारा संदर्भित किया जाता है क्योंकि उन सभी को भी फिर से बनाना होगा।
आर्येह लीब तौआरोग

0

यह क्वेरी नल को स्वतः अपडेट कर देगी

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) DEFAULT 'whatever' NOT NULL;

-6

यह मेरे लिए काम किया: :)

ALTER TABLE your_table_name ADD COLUMN new_column_name int;

2
NOT NULLआपकी क्वेरी पर कोई अड़चन नहीं है । बेशक यह काम कर रहा है।
सिल्वेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.