Использование ALTER для удаления столбца, если он существует в MySQL


Как можно использовать ALTER для удаления столбца в таблице MySQL, если этот столбец существует?

Я знаю, что могу использовать ALTER my_table DROP COLUMN my_column, но это вызовет ошибку, если my_column не существует. Есть ли альтернативный синтаксис для удаления столбца условно?

Я использую MySQL версии 4.0.18.

6 62

6 ответов:

для MySQL нет ни одного: MySQL Feature Request.

разрешить это, возможно, действительно плохая идея, в любом случае:IF EXISTS указывает, что вы выполняете деструктивные операции над базой данных с (для вас) неизвестной структурой. Могут возникнуть ситуации, когда это приемлемо для быстрой и грязной локальной работы, но если вы испытываете соблазн запустить такое заявление против производственных данных (в миграции и т. д.), ты играешь с огнем.

а если вы настаивайте, нетрудно просто проверить наличие первого в клиенте, или поймать ошибку.

MariaDB также поддерживает следующее Начиная с 10.0.2:

DROP [столбец] [если существует] col_name

Я. е.

ALTER TABLE MY_TABLE DROP если существует my_column;

но, возможно, это плохая идея полагаться на нестандартную функцию, поддерживаемую только одной из нескольких вилок MySQL.

в MySQL нет поддержки уровня языка для этого. Вот обходной путь с использованием метаданных MySQL information_schema в 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;

Я написал более подробную информацию в A блоге.

Я только что построил многоразовую процедуру, которая может помочь сделать DROP COLUMN идемпотентна:

-- column_exists:

DROP FUNCTION IF EXISTS column_exists;

DELIMITER $$
CREATE FUNCTION column_exists(
  tname VARCHAR(64),
  cname VARCHAR(64)
)
  RETURNS BOOLEAN
  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

Я знаю, что это старый поток, но есть простой способ справиться с этим требованием без использования хранимых процедур. Это может кому-то помочь.

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 ;

надеюсь, что это поможет кому-то, как это сделал я (после многих проб и ошибок).

ответ Чейза Зайберта работает, но я бы добавил, что если у вас есть несколько схем, вы хотите изменить выбор таким образом:

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

Я понимаю, что эта нить довольно старая сейчас, но у меня была та же проблема. Это было мое самое основное решение с использованием MySQL Workbench, но оно отлично работало...

  1. получить новый редактор sql и выполнить показать таблицы, чтобы получить список ваших таблиц
  2. выбрать все строки и выберите Копировать в буфер обмена (без кавычек) из контекстного меню
  3. вставьте список имен в другую вкладку редактора
  4. напишите свой запрос, т. е. ALTER TABLE x падение a;
  5. сделать некоторые копирования и вставки, так что вы в конечном итоге с отдельный запрос для каждой таблицы
  6. переключить ли верстак должен остановиться при возникновении ошибки
  7. нажмите Выполнить и просмотрите журнал вывода

любые таблицы, которые теперь в таблице не любые таблицы, которые не показали бы ошибку в журналах

тогда вы можете найти / заменить ' drop a 'изменить его на' добавить столбец b INT NULL ' и т. д. и запустить все опять эта штука....

немного неуклюжий, но, наконец, вы получаете конечный результат, и вы можете контролировать/контролировать весь процесс и не забудьте сохранить вам SQL-скрипты, если они вам понадобятся снова.