MySQLに列が存在する場合、ALTERを使用して列を削除する


92

その列が存在する場合、ALTERを使用してMySQLテーブルの列を削除するにはどうすればよいですか?

使用できることはわかっていますがALTER TABLE my_table DROP COLUMN my_columnmy_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のいくつかのフォークのうちの1つだけでサポートされている非標準の機能に依存することは間違いなく悪い考えです。


8
純粋なSQLでそれを行う方法はありますか?
トム

16
ワオ。2005年に言及-9年前。私は...これは、優先度リストの下で推測している
crmpicco

4
MariaDBのサポートそれは10.0.2から始まる
DFR

17
「これを許可することは、間違いなく本当に悪い考えです」—私は同意しません。なぜ誰かがユーザーのユースケースについて推測する必要があるのですか?私はたくさんのデータベースを持っており、それらを同期させる必要があります。ソフトウェアは、人間よりも賢くなりたがっているとき、それは本当に... annoyoingだ
Onkeltem

5
14年経ちましたが、まだありません。私はこれが決して成し遂げられるとは思わない。
スティーブ・ホルヴァート

45

MySQLではこれに対する言語レベルのサポートはありません。これは5.0以降のMySQLinformation_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の貢献をコメントとして要約することが重要だと思いました。なぜなら、それがそれ自体の答えにあるかどうかは明らかではないからです。別のデータベースを変更していないことを確認してください。SELECT* from information_schema.columns WHERE table_name = "country" AND column_name = "updated_at" AND table_schema = DATABASE()\ G
Homer6 2011

「schema_changeが存在する場合はプロシージャを削除する」から警告を受け取りたくない場合。「setsql_notes = 0;」を追加します 最初の行の前に「setsql_notes = 1;」を追加します。最後の行の後。詳細-> stackoverflow.com/questions/27616564/suppress-mysql-warnings
csonuryilmaz 2017年

「区切り文字」には「」を付けないでください(例->区切り文字;;)
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の答えは機能しますが、複数のスキーマがある場合は、次のようにSELECTを変更する必要があることを付け加えておきます。

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

1

おそらく、これを解決する最も簡単な方法(それは機能します)は次のとおりです。

  • CREATE new_table AS SELECT id、col1、col2、...(最終テーブルに実際に必要な列のみ)FROM my_table;

  • my_tableの名前をold_tableに、new_tableの名前を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

このスレッドはかなり古いことに気づきましたが、同じ問題を抱えていました。これはMySQLWorkbenchを使用した非常に基本的なソリューションでしたが、正常に機能しました...

  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.