Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

DROP [COLUMN] [ЕСЛИ СУЩЕСТВУЕТ] col_name

т.е.

ALTER TABLE my_table DROP IF EXISTS my_column;

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

Ответ 2

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

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

Ответ 3

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

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 ;

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

Ответ 4

Я только что создал процедуру многократного использования, которая может помочь сделать 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=...

Ответ 6

Возможно, самый простой способ решить эту проблему (это сработает):

  • CREATE new_table AS SELECT id, col1, col2,... (только те столбцы, которые вам действительно нужны в финальной таблице) FROM my_table;

  • ИЗМЕНИТЬ my_table TO old_table, new_table TO my_table;

  • DROP old_table;

Или сохраните old_table для отката, если это необходимо.

Это будет работать, но внешние ключи не будут перемещены. Вы должны будете повторно добавить их в my_table позже; также внешние ключи в других таблицах, которые ссылаются на my_table, должны быть исправлены (указывает на новую my_table).

Удачи...

Ответ 7

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

  • получите новый редактор sql и запустите SHOW TABLES, чтобы получить список ваших таблиц.
  • выберите все строки и выберите копию в буфер обмена (без кавычек) из контекстного меню
  • вставьте список имен в другую вкладку редактора.
  • напишите свой запрос, то есть ALTER TABLE x DROP a;
  • выполните некоторые операции копирования и вставки, поэтому вы получите отдельный запрос для каждой таблицы.
  • Переключить, должен ли рабочий стол останавливаться при возникновении ошибки.
  • Хит выполняется и просматривает журнал вывода

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

то вы можете найти/заменить "drop a" изменить его на "ADD COLUMN b INT NULL" и т.д. и снова запустить все это.

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