Использование ALTER для удаления столбца, если он существует в MySQL
Как можно использовать ALTER для удаления столбца в таблице MySQL, если этот столбец существует?
Я знаю, что могу использовать ALTER TABLE my_table DROP COLUMN my_column
, но это приведет к ошибке, если my_column
не существует. Есть ли альтернативный синтаксис для условного удаления столбца?
Я использую MySQL версии 4.0.18.
Ответы
Ответ 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-скрипты, если они вам понадобятся.