यदि यह MySQL में मौजूद है, तो किसी कॉलम को छोड़ने के लिए ALTER का उपयोग करना


92

यदि कोई स्तंभ मौजूद है, तो MySQL तालिका में किसी स्तंभ को छोड़ने के लिए ALTER का उपयोग कैसे किया जा सकता है?

मुझे पता है कि मैं उपयोग कर सकता हूं ALTER TABLE my_table DROP COLUMN my_column, लेकिन अगर my_columnमौजूद नहीं है तो एक त्रुटि फेंक देगा । क्या कॉलम को सशर्त रूप से छोड़ने के लिए वैकल्पिक वाक्यविन्यास है?

मैं MySQL संस्करण 4.0.18 का उपयोग कर रहा हूं।


6
मेटा पर इस प्रश्न का उल्लेख किया गया था ।
बस एक छात्र

जवाबों:


70

MySQL के लिए, कोई नहीं है: MySQL फ़ीचर रिक्वेस्ट

यह अनुमति देना यकीनन एक बुरा विचार है, वैसे भी: IF EXISTSइंगित करता है कि आप अज्ञात संरचना के साथ डेटाबेस पर विनाशकारी संचालन चला रहे हैं। ऐसी परिस्थितियां हो सकती हैं जहां यह त्वरित और गंदे स्थानीय काम के लिए स्वीकार्य है, लेकिन यदि आपको उत्पादन डेटा (एक माइग्रेशन आदि) के खिलाफ इस तरह के बयान को चलाने के लिए लुभाया जाता है, तो आप आग से खेल रहे हैं।

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

MariaDB भी 10.0.2 से शुरू होने वाले निम्नलिखित का समर्थन करता है:

DROP [COLUMN] [IF EXISTS] col_name 

अर्थात

ALTER TABLE my_table DROP IF EXISTS my_column;

लेकिन MySQL के कई कांटे में से केवल एक के द्वारा समर्थित गैर-मानक सुविधा पर भरोसा करना एक बुरा विचार है।


8
क्या शुद्ध SQL में ऐसा करने का कोई तरीका है?
टॉम

16
वाह। 9 साल पहले 2005 में उल्लेख किया गया था। मैं अनुमान लगा रहा हूं कि यह प्राथमिकता सूची में नीचे है ...
काम्पिसको

4
मारियाडीबी इसका समर्थन करता है जो 10.0.2 से शुरू होता है
डीएफआर

17
"यह अनुमति देना यकीनन एक बुरा विचार है," - मैं सहमत नहीं हूँ। उपयोगकर्ताओं को मामलों का उपयोग करने के बारे में धारणा क्यों करनी चाहिए? मेरे पास डेटाबेस का एक गुच्छा है और मुझे उन्हें सिंक में लाने की आवश्यकता है। यह वास्तव में कष्टप्रद है जब सॉफ्टवेयर मानव की तुलना में अधिक स्मार्ट होना चाहता है ...
ओंकेल्टेम

5
14 साल, अभी भी वहाँ नहीं है। मुझे नहीं लगता कि यह कभी पूरा हो पाएगा।
स्टीव होर्वाथ

45

MySQL में इसके लिए कोई भाषा स्तर का समर्थन नहीं है। यहां 5.0+ में MySQL information_schema मेटा-डेटा को शामिल करने वाला एक काम है, लेकिन यह 4.0.18 में आपके मुद्दे को संबोधित नहीं करेगा।

drop procedure if exists schema_change;

delimiter ';;'
create procedure schema_change() begin

    /* delete columns if they exist */
    if exists (select * from information_schema.columns where table_schema = schema() and table_name = 'table1' and column_name = 'column1') then
        alter table table1 drop column `column1`;
    end if;
    if exists (select * from information_schema.columns where table_schema = schema() and table_name = 'table1' and column_name = 'column2') then
        alter table table1 drop column `column2`;
    end if;

    /* add columns */
    alter table table1 add column `column1` varchar(255) NULL;
    alter table table1 add column `column2` varchar(255) NULL;

end;;

delimiter ';'
call schema_change();

drop procedure if exists schema_change;

मैंने एक ब्लॉग पोस्ट में कुछ और विस्तृत जानकारी लिखी ।


3
मुझे लगा कि DrHyde के योगदान को एक टिप्पणी के रूप में संक्षेप में प्रस्तुत करना महत्वपूर्ण है, क्योंकि यह स्पष्ट नहीं है जब यह स्वयं के उत्तर में है। सुनिश्चित करें कि आप यह जाँचते हैं कि आपका एक अलग डेटाबेस को संशोधित नहीं कर रहा है: info_schema.columns WHERE से तालिका_नाम = "देश" और स्तंभ_नाम = "अपडेट किया गया" और तालिका_काथी = डेटा = (जी)
होमर ६

यदि आप स्कीमा प्रक्रिया को स्कीमा_क्रूज मौजूद होने पर चेतावनी प्राप्त नहीं करना चाहते हैं; "sql_notes = 0 सेट करें" जोड़ें पहली पंक्ति से पहले और "सेट sql_notes = 1;" अंतिम पंक्ति के बाद। विवरण -> stackoverflow.com/questions/27616564/suppress-mysql-warnings
csonuryilmaz

"सीमांकक" बिना '' होना चाहिए (जैसे -> परिसीमन ;;)
इलिदान

17

मुझे पता है कि यह एक पुराना धागा है, लेकिन संग्रहीत प्रक्रियाओं का उपयोग किए बिना इस आवश्यकता को संभालने का एक सरल तरीका है। इससे किसी की मदद हो सकती है।

set @exist_Check := (
    select count(*) from information_schema.columns 
    where TABLE_NAME='YOUR_TABLE' 
    and COLUMN_NAME='YOUR_COLUMN' 
    and TABLE_SCHEMA=database()
) ;
set @sqlstmt := if(@exist_Check>0,'alter table YOUR_TABLE drop column YOUR_COLUMN', 'select ''''') ;
prepare stmt from @sqlstmt ;
execute stmt ;

आशा है कि यह किसी की मदद करता है, जैसा कि उसने मुझे किया था (बहुत परीक्षण और त्रुटि के बाद)।


यह ज़रूर किया। धन्यवाद @ प्रदीप
सुमित देशमुख

14

मैंने बस एक पुन: प्रयोज्य प्रक्रिया का निर्माण किया है जो कि DROP COLUMNबेरोजगार बनाने में मदद कर सकती है :

-- column_exists:

DROP FUNCTION IF EXISTS column_exists;

DELIMITER $$
CREATE FUNCTION column_exists(
  tname VARCHAR(64),
  cname VARCHAR(64)
)
  RETURNS BOOLEAN
  READS SQL DATA
  BEGIN
    RETURN 0 < (SELECT COUNT(*)
                FROM `INFORMATION_SCHEMA`.`COLUMNS`
                WHERE `TABLE_SCHEMA` = SCHEMA()
                      AND `TABLE_NAME` = tname
                      AND `COLUMN_NAME` = cname);
  END $$
DELIMITER ;

-- drop_column_if_exists:

DROP PROCEDURE IF EXISTS drop_column_if_exists;

DELIMITER $$
CREATE PROCEDURE drop_column_if_exists(
  tname VARCHAR(64),
  cname VARCHAR(64)
)
  BEGIN
    IF column_exists(tname, cname)
    THEN
      SET @drop_column_if_exists = CONCAT('ALTER TABLE `', tname, '` DROP COLUMN `', cname, '`');
      PREPARE drop_query FROM @drop_column_if_exists;
      EXECUTE drop_query;
    END IF;
  END $$
DELIMITER ;

उपयोग:

CALL drop_column_if_exists('my_table', 'my_column');

उदाहरण:

SELECT column_exists('my_table', 'my_column');       -- 1
CALL drop_column_if_exists('my_table', 'my_column'); -- success
SELECT column_exists('my_table', 'my_column');       -- 0
CALL drop_column_if_exists('my_table', 'my_column'); -- success
SELECT column_exists('my_table', 'my_column');       -- 0

5

चेस सीबार्ट का जवाब काम करता है, लेकिन मैं यह जोड़ूंगा कि अगर आपके पास कई स्कीमाटा हैं तो आप सेलेक्ट को बदलना चाहते हैं:

select * from information_schema.columns where table_schema in (select schema()) and table_name=...

1

शायद इसे हल करने का सबसे सरल तरीका है (यह काम करेगा):

  • New_table के रूप में चयन करें id, col1, col2, ... (केवल वही कॉलम जो आप वास्तव में अंतिम तालिका में चाहते हैं) my_table से;

  • RENAME my_table to old_table, new_table TO my_table;

  • DROP old_table;

या जरूरत पड़ने पर रोलबैक के लिए old_table रखें।

यह काम करेगा लेकिन विदेशी कुंजियों को स्थानांतरित नहीं किया जाएगा। आपको बाद में उन्हें my_table में फिर से जोड़ना होगा; अन्य तालिकाओं में भी विदेशी कुंजियाँ जो my_table को संदर्भित करती हैं, उन्हें ठीक करना होगा (नए my_table को इंगित किया गया है)।

शुभ लाभ...


1

आप इस स्क्रिप्ट का उपयोग कर सकते हैं, अपने कॉलम, स्कीमा और टेबल नाम का उपयोग कर सकते हैं

 IF EXISTS (SELECT *
                         FROM INFORMATION_SCHEMA.COLUMNS
                         WHERE TABLE_NAME = 'TableName' AND COLUMN_NAME = 'ColumnName' 
                                             AND TABLE_SCHEMA = SchemaName)
    BEGIN
       ALTER TABLE TableName DROP COLUMN ColumnName;
    END;


-3

मुझे महसूस हुआ कि यह धागा अभी काफी पुराना है, लेकिन मुझे भी यही समस्या हो रही थी। यह MySQL कार्यक्षेत्र का उपयोग करके मेरा बहुत ही बुनियादी समाधान था, लेकिन यह ठीक काम करता है ...

  1. एक नया sql संपादक प्राप्त करें और अपनी तालिकाओं की सूची प्राप्त करने के लिए SHOW TABLES निष्पादित करें
  2. सभी पंक्तियों का चयन करें, और संदर्भ मेनू से क्लिपबोर्ड (अयोग्य) की प्रतिलिपि चुनें
  3. नामों की सूची को दूसरे संपादक टैब में पेस्ट करें
  4. अपनी क्वेरी लिखें, यानी TABLE xDROP a;
  5. कुछ कॉपी और पेस्टिंग करें, ताकि आप प्रत्येक तालिका के लिए अलग क्वेरी के साथ समाप्त हो जाएं
  6. कोई त्रुटि होने पर कार्यक्षेत्र को रोकना चाहिए या नहीं टॉगल करें
  7. निष्पादित करें और आउटपुट लॉग के माध्यम से देखें

जिन तालिकाओं में तालिका थी, उनमें अब कोई तालिका नहीं है, जिसने लॉग में कोई त्रुटि नहीं दिखाई होगी

तब आप 'ड्रॉप a' को 'ADD COLUMN bINT NULL' आदि में बदल सकते हैं / बदल सकते हैं और फिर से पूरी चीज़ चला सकते हैं ...।

थोड़ा भद्दा, लेकिन अंत में आपको अंतिम परिणाम मिलता है और आप पूरी प्रक्रिया को नियंत्रित / निगरानी कर सकते हैं और याद रख सकते हैं कि आपको फिर से ज़रूरत पड़ने पर sql स्क्रिप्ट को बचाने के लिए।

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