Postgresql - एक varchar कॉलम का आकार कम लंबाई में बदलें


153

मेरे पास ALTER TABLEवास्तव में बड़ी तालिका (लगभग 30 लाखों पंक्तियों) पर कमांड के बारे में एक प्रश्न है । इसका एक कॉलम एक है varchar(255)और मैं इसे आकार बदलना चाहूंगा varchar(40)। मूल रूप से, मैं निम्न कमांड चलाकर अपना कॉलम बदलना चाहूंगा:

ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40);

यदि प्रक्रिया बहुत लंबी है तो मुझे कोई समस्या नहीं है लेकिन ऐसा लगता है कि मेरी तालिका ALTER TABLE कमांड के दौरान अधिक पठनीय नहीं है। क्या कोई स्मार्ट तरीका है? हो सकता है कि एक नया कॉलम जोड़ें, पुराने कॉलम से मान कॉपी करें, पुराना कॉलम ड्रॉप करें और अंत में नया नाम बदलें?

किसी भी सुराग बहुत सराहना की जाएगी! अग्रिम में धन्यवाद,

नोट: मैं PostgreSQL 9.0 का उपयोग करता हूं।


11
बस स्पष्ट होने के लिए: आप जानते हैं, कि resizingटेबल को कम जगह नहीं मिलेगी?
एएच

मेरे मामले में भी? मेरा मतलब है कि कॉलम में 255 के बजाय अधिकतम 40 char (so octets) का आकार होगा?
लेबिनोकल

16
यदि आप varchar(255)PostgreSQL से कहते हैं तो यह 255 बाइट्स को एक मान के लिए आवंटित नहीं करेगा जो कि वास्तविक लंबाई 40 बाइट्स है। यह 40 बाइट्स (साथ ही कुछ आंतरिक ओवरहेड) आवंटित करेगा। केवल एक चीज जो be changed by the ALTER TABLE` है, आप उस कॉलम में अधिकतम बाइट्स स्टोर कर सकते हैं जो PG से कोई त्रुटि प्राप्त किए बिना किया जा सकता है।
एएच

ओवरहेड AH के बारे में उल्लेख किया गया: varchar (n) के लिए ओवरहेड क्या है?
एरविन ब्रैंडसेटर

अपडेट के लिए यहां उत्तर की जाँच करें dba.stackexchange.com/questions/189890/…
इवान कैरोल

जवाबों:


73

डेटा बदलने के बिना PostgreSQL तालिका में एक कॉलम का आकार बदलने के लिए ऐसा करने का विवरण है । आपको डेटाबेस कैटलॉग डेटा को हैक करना होगा। आधिकारिक तौर पर ऐसा करने का एकमात्र तरीका ALTER TABLE के साथ है, और जैसा कि आपने नोट किया है कि परिवर्तन चालू होने के दौरान पूरी तालिका को लॉक और फिर से लिख देगा।

सुनिश्चित करें कि आपने इसे बदलने से पहले डॉक्स के चरित्र प्रकार अनुभाग को पढ़ा है । यहाँ पर जागरूक होने के लिए सभी प्रकार के अजीब मामले। लंबाई की जाँच तब की जाती है जब मूल्यों को पंक्तियों में संग्रहीत किया जाता है। यदि आप वहां कम सीमा हैक करते हैं, तो यह मौजूदा मूल्यों के आकार को कम नहीं करेगा। आपको यह समझदारी होगी कि परिवर्तन करने के बाद पंक्तियों की तलाश में पूरी मेज पर एक स्कैन करना चाहिए जहाँ फ़ील्ड की लंबाई> 40 अक्षर है। आपको यह पता लगाना होगा कि उन लोगों को मैन्युअल रूप से कैसे काट दिया जाए - तो आप कुछ ओवरों को सिर्फ ओवरसाइज़ पर लौटाते हैं - क्योंकि अगर कोई उस पंक्ति पर कुछ भी अपडेट करने की कोशिश करता है, तो वह इसे अभी भी अस्वीकार कर सकता है, इस बिंदु पर यह पंक्ति के नए संस्करण को संग्रहीत करने के लिए जाता है। प्रफुल्लितता उपयोगकर्ता के लिए ensues।

VARCHAR एक भयानक प्रकार है जो केवल SQL मानक के अपने संबंधित भयानक भाग के अनुपालन के लिए PostgreSQL में मौजूद है। यदि आप बहु-डेटाबेस संगतता के बारे में परवाह नहीं करते हैं, तो अपने डेटा को पाठ के रूप में संग्रहीत करने पर विचार करें और इसकी लंबाई को सीमित करने के लिए एक बाधा जोड़ें। इस तालिका लॉक / पुनर्लेखन समस्या के बिना आप बाधाएं बदल सकते हैं, और वे केवल कमज़ोर लंबाई जाँच की तुलना में अधिक अखंडता जाँच कर सकते हैं।


जवाब के लिए धन्यवाद। मैं आपके लिंक की जाँच करूँगा। मुझे मैन्युअल आकार की जाँच की चिंता नहीं है क्योंकि मेरी सभी सामग्री में अधिकतम 40 वर्ण हैं। मुझे पाठ पर बाधा के बारे में और अधिक पढ़ने की आवश्यकता है क्योंकि मेरा मानना ​​है कि VARCHAR को lentgh की जाँच करना बेहतर था :)
Labynocle

6
परिवर्तन varchar लंबाई तालिका को फिर से लिखना नहीं है। यह सिर्फ पूरी तालिका के खिलाफ कसना लंबाई की जाँच करें जैसा कि ठीक है। यदि आप लंबाई बढ़ाते हैं, तो कुछ नहीं करना है, बस अगली प्रविष्टि या अपडेट बड़ी लंबाई को स्वीकार करेंगे। यदि आप लंबाई कम करते हैं और सभी पंक्तियाँ नए छोटे अवरोध से गुजरती हैं, तो Pg अगली आवेषण या अपडेट को केवल नई लंबाई लिखने की अनुमति देने के अलावा कोई और कार्रवाई नहीं करता है।
मनिएरो

3
@bigown, स्पष्ट करने के लिए, आपका कथन केवल PostgreSQL 9.2+ के लिए सही है , पुराने वाले नहीं।
माथेउसल 12

12
लिंक अब मर चुका है।
छापे

यह कैसे काम करता है इसके बारे में अधिक जानकारी के लिए dba.stackexchange.com/questions/189890/…
Evan Carroll

100

PostgreSQL 9.1 में एक आसान तरीका है

http://www.postgresql.org/message-id/162867790801110710g3c686010qcdd852e721e7a559@mail.gmail.com

CREATE TABLE foog(a varchar(10));

ALTER TABLE foog ALTER COLUMN a TYPE varchar(30);

postgres=# \d foog

 Table "public.foog"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 a      | character varying(30) |

6
ध्यान दें कि यह केवल इसलिए काम करता है क्योंकि आप बड़े आकार (30> 10) को निर्दिष्ट कर रहे हैं । यदि आकार छोटा है, तो आपको वही त्रुटि मिलेगी जो मैंने की थी
Matthieu

2
Postgres चाहिए नहीं करता है, तो आप एक ALTER तालिका क्वेरी के माध्यम से varchar आकार कम एक त्रुटि फेंक जब तक अधिक पंक्तियों में से एक एक मूल्य है कि नए आकार से बड़ा होता है।
बताएं

@ अच्छा, दिलचस्प। क्या इसका मतलब यह है कि पोस्टग्रैज टेबल का पूरा स्कैन करता है, या किसी तरह अपने आंकड़ों में अधिकतम आकार रखता है?
Matthieu

47

ठीक है, मुझे शायद पार्टी के लिए देर हो रही है, लेकिन ...

वहाँ आपके मामले में रंग प्राप्त करने की जरूरत नहीं है!

पोस्टग्रैज, कुछ अन्य डेटाबेसों के विपरीत, केवल स्ट्रिंग को फिट करने के लिए केवल पर्याप्त स्थान का उपयोग करने के लिए पर्याप्त स्मार्ट है (यहां तक ​​कि लंबे तार के लिए संपीड़न का उपयोग करके), इसलिए भले ही आपका कॉलम VARCHAR (255) के रूप में घोषित किया गया हो - यदि आप 40-वर्ण स्ट्रिंग्स को संग्रहीत करते हैं स्तंभ, अंतरिक्ष उपयोग ओवरहेड के 40 बाइट + 1 बाइट होगा।

एक छोटी स्ट्रिंग (126 बाइट तक) के लिए भंडारण की आवश्यकता 1 बाइट से अधिक वास्तविक स्ट्रिंग है, जिसमें चरित्र के मामले में स्पेस पेडिंग शामिल है। लंबे समय तक तार के बजाय 1 के 4 ओवरहेड होते हैं। लंबे तार स्वचालित रूप से सिस्टम द्वारा संपीड़ित होते हैं, इसलिए डिस्क पर भौतिक आवश्यकता कम हो सकती है। बहुत लंबे मान भी पृष्ठभूमि तालिकाओं में संग्रहीत किए जाते हैं ताकि वे छोटे कॉलम मानों तक तेजी से पहुंच में हस्तक्षेप न करें।

( http://www.postgresql.org/docs/9.0/interactive/datatype-character.html )

VARCHAR में आकार विनिर्देश का उपयोग केवल उन मूल्यों के आकार की जांच करने के लिए किया जाता है, जो डिस्क लेआउट को प्रभावित नहीं करते हैं। वास्तव में, VARCHAR और TEXT फ़ील्ड पोस्टग्रेज़ में उसी तरह संग्रहीत हैं


8
"क्यों" के बारे में अधिक जानकारी जोड़ने के लिए कभी देर नहीं हुई! इस सारी जानकारी के लिए धन्यवाद
Labynocle

कुछ समय के लिए आपको अपने डेटाबेस की संरचना के अनुरूप होना चाहिए। भले ही 2 स्तंभों का कोई संबंध नहीं है, वे अवधारणा के दृष्टिकोण से एक संबंध रख सकते हैं, उदाहरण के लिए मॉडल ईएवी की जांच करें।
अलेक्जेंड्रे

36

मैं एक ही समस्या का सामना कर रहा था 32 से 8 से एक VARCHAR की कोशिश कर रहा है और हो रही है ERROR: value too long for type character varying(8) । मैं यथासंभव एसक्यूएल के करीब रहना चाहता हूं क्योंकि मैं स्व-निर्मित जेपीए जैसी संरचना का उपयोग कर रहा हूं जिसे हमें ग्राहक की पसंद (पोस्टग्रेक्यूएल डिफ़ॉल्ट एक) के अनुसार अलग-अलग डीबीएमएस पर स्विच करना पड़ सकता है। इसलिए, मैं सिस्टम तालिकाओं को बदलने की चाल का उपयोग नहीं करना चाहता।

मैंने इस USINGकथन का उपयोग किया ALTER TABLE:

ALTER TABLE "MY_TABLE" ALTER COLUMN "MyColumn" TYPE varchar(8)
USING substr("MyColumn", 1, 8)

जैसा कि @raylu ने उल्लेख किया है, ALTERतालिका पर एक विशेष ताला प्राप्त करता है , इसलिए जब तक यह पूरा नहीं हो जाता तब तक अन्य सभी कार्यों में देरी होगी।


2
ALTERतालिका से रोकती है पर एक विशेष ताला प्राप्त सभी अन्य कार्यों
raylu

8

नया कॉलम जोड़ना और पुराने के साथ नए की जगह मेरे लिए काम किया, redshift postgresql पर, अधिक जानकारी के लिए इस लिंक को देखें https://gist.github.com/mmasashi/7107430

BEGIN;
LOCK users;
ALTER TABLE users ADD COLUMN name_new varchar(512) DEFAULT NULL;
UPDATE users SET name_new = name;
ALTER TABLE users DROP name;
ALTER TABLE users RENAME name_new TO name;
END;

7

यहाँ ग्रेग स्मिथ द्वारा वर्णित पृष्ठ का कैश दिया गया है। इस मामले में, जैसे ही मृत्यु हो जाती है, परिवर्तन कथन इस तरह दिखता है:

UPDATE pg_attribute SET atttypmod = 35+4
WHERE attrelid = 'TABLE1'::regclass
AND attname = 'COL1';

जहां आपकी तालिका TABLE1 है, स्तंभ COL1 है और आप इसे 35 वर्णों पर सेट करना चाहते हैं (लिंक के अनुसार विरासत उद्देश्यों के लिए +4 की आवश्यकता है, संभवतः ओवरहेड को टिप्पणियों में AH द्वारा संदर्भित किया गया है)।


7

यदि आप लेन-देन में परिवर्तन करते हैं तो तालिका को लॉक नहीं किया जाना चाहिए:

BEGIN;
  ALTER TABLE "public"."mytable" ALTER COLUMN "mycolumn" TYPE varchar(40);
COMMIT;

यह मेरे लिए तेजी से धधकते हुए काम करता है, 400 सेकंड से अधिक पंक्तियों वाली एक मेज पर कुछ सेकंड।


5
आप ALTERकथन के लॉकिंग व्यवहार को बदलने के लिए स्पष्ट लेनदेन आवरण की अपेक्षा क्यों करेंगे ? यह नहीं है
एरविन ब्रान्डसेट्टर

लेन-देन के आवरण के साथ और उसके बिना अपने आप को आज़माएं, आपको भारी अंतर दिखाई देगा।
जैकट्रेड

2
प्रिंसिपल पर आपका जवाब गलत है। स्पष्ट लेनदेन आवरण के बिना कोई भी डीडीएल बयान निहित लेनदेन के अंदर चलता है। स्पष्ट लेनदेन का एकमात्र संभावित प्रभाव यह है कि ताले को लंबे समय तक रखा जाता है - स्पष्ट तक COMMIT। रैपर केवल तभी समझ में आता है जब आप एक ही लेनदेन में अधिक कमांड डालना चाहते हैं।
एरविन ब्रान्डसेट्टर 13

आप पूरी तरह से सही हैं, लेकिन मैं जोर देता हूं: अपने आप को आज़माएं, आगे बढ़ें। और फिर पूछें कि उसी तरह से काम क्यों नहीं कर रहा है।
जैकट्रेड

Postgres 9.3 पर मदद नहीं की।
नौमेनन

1

मैंने आकार बदलने का एक बहुत ही आसान तरीका खोजा है, यानी एनोटेशन @Size (min = 1, max = 50) जो कि "import javax.validation.constraints" यानी "आयात javax.validation.constraints.Size" का हिस्सा है;

@Size(min = 1, max = 50)
private String country;


when executing  this is hibernate you get in pgAdmin III 


CREATE TABLE address
(
.....
  country character varying(50),

.....

)

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

0

परिवर्तन तालिका के बाद चलाने का प्रयास करें:

ALTER TABLE public.users 
ALTER COLUMN "password" TYPE varchar(300) 
USING "password"::varchar;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.