ใช้ ALTER เพื่อวางคอลัมน์หากมีอยู่ใน MySQL


92

จะใช้ ALTER เพื่อวางคอลัมน์ในตาราง MySQL ได้อย่างไรหากมีคอลัมน์นั้นอยู่

ฉันรู้ว่าฉันสามารถใช้ได้ALTER TABLE my_table DROP COLUMN my_columnแต่นั่นจะทำให้เกิดข้อผิดพลาดหากmy_columnไม่มีอยู่ มีไวยากรณ์อื่นสำหรับวางคอลัมน์ตามเงื่อนไขหรือไม่?

ฉันใช้ MySQL เวอร์ชัน 4.0.18


6
คำถามนี้ได้รับการกล่าวถึงในMeta
แค่นักเรียน

คำตอบ:


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
ว้าว. กล่าวถึงในปี 2548 - 9 ปีที่แล้ว ฉันเดาว่านี่เป็นรายการลำดับความสำคัญ ...
crmpicco

4
MariaDB รองรับตั้งแต่ 10.0.2
Dfr

17
"การปล่อยให้สิ่งนี้เป็นความคิดที่ไม่ดีจริงๆ" - ฉันไม่เห็นด้วย เหตุใดจึงควรตั้งสมมติฐานเกี่ยวกับกรณีการใช้งานของผู้ใช้ ฉันมีฐานข้อมูลจำนวนมากและต้องการซิงค์ มันน่ารำคาญจริงๆเมื่อซอฟต์แวร์ต้องการที่จะฉลาดกว่ามนุษย์ ...
Onkeltem

5
14 ปีก็ยังไม่มี ฉันไม่คิดว่าสิ่งนี้จะทำได้สำเร็จ
Steve Horvath

45

ไม่มีการรองรับระดับภาษาสำหรับสิ่งนี้ใน MySQL นี่คือวิธีแก้ปัญหาที่เกี่ยวข้องกับ MySQL information_schema meta-data ใน 5.0+ แต่จะไม่แก้ไขปัญหาของคุณใน 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 เป็นความคิดเห็นเป็นสิ่งสำคัญเพราะมันไม่ชัดเจนเมื่ออยู่ในคำตอบของตัวเอง ตรวจสอบว่าคุณไม่ได้แก้ไขฐานข้อมูลอื่น: SELECT * จาก information_schema.columns WHERE table_name = "country" AND column_name = "updated_at" AND table_schema = DATABASE () \ G
Homer6

หากคุณไม่ต้องการรับคำเตือนจาก "ขั้นตอนการวางหากมีอยู่ schema_change;" เพิ่ม "set sql_notes = 0;" ก่อนบรรทัดแรกและเพิ่ม "set sql_notes = 1;" หลังจากบรรทัดสุดท้าย รายละเอียด -> stackoverflow.com/questions/27616564/suppress-mysql-warnings
csonuryilmaz

"ตัวคั่น" ควรจะไม่มี "(เช่น -> ตัวคั่น ;;)
Illidan

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 ;

หวังว่านี่จะช่วยใครบางคนเหมือนฉัน (หลังจากลองผิดลองถูกมาหลายครั้ง)


มันทำได้แน่นอน ขอบคุณ @Pradeep
Sumit Deshmukh

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

คำตอบของ Chase Seibert ใช้งานได้ แต่ฉันจะเพิ่มว่าหากคุณมี schemata หลายรายการที่คุณต้องการแก้ไข SELECT ดังนี้:

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

1

บางทีวิธีที่ง่ายที่สุดในการแก้ปัญหานี้ (ซึ่งจะได้ผล) คือ:

  • สร้าง new_table เป็น SELECT 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 ใหม่)

โชคดี...



-3

ฉันรู้ว่าเธรดนี้ค่อนข้างเก่าแล้ว แต่ฉันก็ประสบปัญหาเดียวกัน นี่เป็นวิธีแก้ปัญหาพื้นฐานของฉันโดยใช้ MySQL Workbench แต่ก็ใช้งานได้ดี ...

  1. รับโปรแกรมแก้ไข sql ใหม่และเรียกใช้ SHOW TABLES เพื่อรับรายการตารางของคุณ
  2. เลือกแถวทั้งหมดและเลือกคัดลอกไปยังคลิปบอร์ด (ไม่ได้ใส่เครื่องหมายคำพูด) จากเมนูบริบท
  3. วางรายชื่อลงในแท็บตัวแก้ไขอื่น
  4. เขียนคำถามของคุณเช่น ALTER TABLE xDROP a;
  5. ทำการคัดลอกและวางดังนั้นคุณจะได้รับแบบสอบถามแยกกันสำหรับแต่ละตาราง
  6. สลับว่าโต๊ะทำงานควรหยุดเมื่อเกิดข้อผิดพลาดหรือไม่
  7. กดดำเนินการและดูบันทึกผลลัพธ์

ตารางใด ๆ ที่มีตารางในขณะนี้ไม่มีตารางใดที่จะไม่แสดงข้อผิดพลาดในบันทึก

จากนั้นคุณสามารถค้นหา / แทนที่ 'drop a' เปลี่ยนเป็น 'ADD COLUMN bINT NULL' ฯลฯ และเรียกใช้สิ่งทั้งหมดอีกครั้ง ...

ค่อนข้างอึดอัด แต่ในที่สุดคุณก็จะได้ผลลัพธ์และคุณสามารถควบคุม / ตรวจสอบกระบวนการทั้งหมดได้และอย่าลืมบันทึกสคริปต์ sql ในกรณีที่คุณต้องการอีก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.