MySQL'de varsa bir sütun bırakmak için ALTER kullanma


92

Bir MySQL tablosundaki bir sütun varsa, bu sütun varsa ALTER nasıl kullanılabilir?

Kullanabileceğimi biliyorum ALTER TABLE my_table DROP COLUMN my_column, ancak yoksa my_columnbu bir hata verecektir . Sütunu koşullu olarak kaldırmak için alternatif sözdizimi var mı?

MySQL 4.0.18 sürümünü kullanıyorum.


6
Bu soru bahsedildi Meta .
Sadece bir öğrenci

Yanıtlar:


70

MySQL için hiçbiri yoktur: MySQL Özellik İsteği .

Buna izin vermek tartışmasız gerçekten kötü bir fikirdir: IF EXISTS(size) bilinmeyen bir yapıya sahip bir veritabanı üzerinde yıkıcı işlemler yürüttüğünüzü gösterir. Hızlı ve kirli yerel işler için bunun kabul edilebilir olduğu durumlar olabilir, ancak üretim verilerine (bir geçişte vb.) Karşı böyle bir açıklama yapmaya meyilliyseniz, ateşle oynuyorsunuz.

Ancak ısrar ederseniz, önce istemcide var olup olmadığını kontrol etmek veya hatayı yakalamak zor değildir.

MariaDB ayrıca 10.0.2'den başlayarak aşağıdakileri de destekler:

DROP [COLUMN] [IF EXISTS] col_name 

yani

ALTER TABLE my_table DROP IF EXISTS my_column;

Ancak, MySQL'in birkaç çatalından yalnızca biri tarafından desteklenen standart olmayan bir özelliğe güvenmek tartışmasız kötü bir fikirdir.


8
Bunu saf SQL'de yapmanın bir yolu var mı?
Tom

16
Vay. 2005 - 9 yıl önce bahsedildi. Sanırım bu öncelik listesinde ...
crmpicco

4
MariaDB, 10.0.2
Dfr

17
"Buna izin vermek tartışmalı olarak gerçekten kötü bir fikir" - Katılmıyorum. Kullanıcıların kullanım durumları hakkında neden varsayımlarda bulunulmalıdır? Bir sürü veritabanım var ve onları senkronize etmem gerekiyor. Yazılımın insandan daha akıllı olmak istemesi gerçekten can sıkıcı ...
Onkeltem

5
14 yıl geçti, hala orada değil. Bunun asla yapılacağını sanmıyorum.
Steve Horvath

45

MySQL'de bunun için dil seviyesi desteği yoktur. İşte 5.0+ sürümündeki MySQL information_schema meta verilerini içeren bir çözüm, ancak sorununuzu 4.0.18'de ele almayacaktır.

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;

Bir blog yazısına biraz daha detaylı bilgi yazdım .


3
DrHyde'nin katkısını bir yorum olarak özetlemenin önemli olduğunu düşündüm, çünkü kendi başına bir cevap olduğunda bu belli değil. Farklı bir veritabanını değiştirmediğinizden emin olun: SELECT * from information_schema.columns WHERE table_name = "country" AND column_name = "updated_at" AND table_schema = DATABASE () \ G
Homer6

"Eğer varsa bırak yordamı schema_change;" den uyarı almak istemiyorsanız; "set sql_notes = 0;" ilk satırdan önce ve "set sql_notes = 1" ekleyin; son satırdan sonra. Ayrıntılar -> stackoverflow.com/questions/27616564/suppress-mysql-warnings
csonuryilmaz

"sınırlayıcı" içermemelidir '' (örneğin -> ayırıcı ;;)
Illidan

17

Bunun eski bir iş parçacığı olduğunu biliyorum, ancak bu gereksinimi saklı yordamları kullanmadan karşılamanın basit bir yolu var. Bu birine yardımcı olabilir.

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 ;

Umarım bu, bana yaptığı gibi birine yardımcı olur (birçok deneme yanılma sonrasında)


Kesinlikle yaptı. Teşekkürler @Pradeep
Sumit Deshmukh

14

Az önce DROP COLUMNidempotent yapmaya yardımcı olabilecek yeniden kullanılabilir bir prosedür geliştirdim :

-- 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 ;

Kullanım:

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

Misal:

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'in cevabı işe yarıyor, ancak ekleyeceğim, eğer birkaç şemanız varsa, SELECT'i şu şekilde değiştirmek istiyorsunuz:

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

1

Belki de bunu çözmenin en basit yolu (işe yarayacak) şudur:

  • Yeni_tablo OLUŞTURMA SEÇİMİ id, col1, col2, ... (sadece final tablosunda gerçekten istediğiniz sütunlar) my_table;

  • My_table'ı old_table, new_table TO my_table;

  • DROP old_table;

Veya gerekirse bir geri alma işlemi için old_table'ı tutun.

Bu işe yarayacak, ancak yabancı anahtarlar taşınmayacaktır. Onları daha sonra my_table'a tekrar eklemeniz gerekir; ayrıca my_table'a başvuran diğer tablolardaki yabancı anahtarların da düzeltilmesi gerekir (yeni my_table'a işaret edilir).

İyi şanslar...



-3

Bu iş parçacığının artık oldukça eski olduğunu anlıyorum, ama aynı sorunu yaşıyordum. Bu MySQL Workbench'i kullanan en temel çözümümdü, ancak iyi çalıştı ...

  1. yeni bir sql editörü edinin ve tablolarınızın bir listesini almak için SHOW TABLES komutunu çalıştırın
  2. tüm satırları seçin ve bağlam menüsünden panoya kopyalamayı (alıntı yapılmamış) seçin
  3. isim listesini başka bir düzenleyici sekmesine yapıştırın
  4. Sorgunuzu yazın, yani ALTER TABLE xDROP a;
  5. biraz kopyalama ve yapıştırma yapın, böylece her tablo için ayrı bir sorgu elde edersiniz
  6. Bir hata oluştuğunda tezgahın durması gerekip gerekmediğini değiştirin
  7. Çalıştır'a basın ve çıktı günlüğüne bakın

Tabloyu içeren tablolar artık günlüklerde hata göstermeyen hiçbir tablo içermiyor

daha sonra 'damla a' bulabilir / değiştirebilir, onu 'SÜTUN EKLE bNULL' vb. olarak değiştirebilir ve her şeyi tekrar çalıştırabilirsiniz ...

biraz hantal, ama sonunda nihai sonucu alırsınız ve tüm süreci kontrol edebilir / izleyebilir ve tekrar ihtiyacınız olması durumunda size sql komut dosyalarını kaydetmeyi unutmayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.