Como ALTER pode ser usado para eliminar uma coluna em uma tabela MySQL se essa coluna existir?
Sei que posso usar ALTER TABLE my_table DROP COLUMN my_column
, mas isso vai dar um erro se my_column
não existir. Existe uma sintaxe alternativa para descartar a coluna condicionalmente?
Estou usando o MySQL versão 4.0.18.
Respostas:
Para MySQL, não há nenhum: Solicitação de recurso MySQL .
Permitir isso é sem dúvida uma ideia muito ruim, de qualquer maneira:
IF EXISTS
indica que você está executando operações destrutivas em um banco de dados com (para você) estrutura desconhecida. Pode haver situações em que isso seja aceitável para trabalho local rápido e sujo, mas se você estiver tentado a executar tal instrução em dados de produção (em uma migração etc.), você está brincando com fogo.Mas se você insiste, não é difícil simplesmente verificar a existência primeiro no cliente ou detectar o erro.
MariaDB também suporta o seguinte, começando com 10.0.2:
DROP [COLUMN] [IF EXISTS] col_name
ie
ALTER TABLE my_table DROP IF EXISTS my_column;
Mas é indiscutivelmente uma má ideia confiar em um recurso não padrão suportado por apenas um dos vários fork do MySQL.
fonte
Não há suporte de nível de idioma para isso no MySQL. Aqui está uma solução alternativa envolvendo metadados information_schema do MySQL no 5.0+, mas não resolverá o seu problema no 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;
Escrevi algumas informações mais detalhadas em uma postagem do blog .
fonte
Eu sei que este é um segmento antigo, mas há uma maneira simples de lidar com esse requisito sem usar procedimentos armazenados. Isso pode ajudar alguém.
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 ;
Espero que isso ajude alguém, assim como a mim (depois de muitas tentativas e erros).
fonte
Acabei de construir um procedimento reutilizável que pode ajudar a tornar
DROP COLUMN
idempotente:-- 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 ;
Uso:
CALL drop_column_if_exists('my_table', 'my_column');
Exemplo:
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
fonte
A resposta de Chase Seibert funciona, mas eu acrescentaria que, se você tiver vários esquemas, deseja alterar o SELECT assim:
select * from information_schema.columns where table_schema in (select schema()) and table_name=...
fonte
Talvez a maneira mais simples de resolver isso (que funcione) seja:
CREATE new_table AS SELECT id, col1, col2, ... (somente as colunas que você realmente deseja na tabela final) FROM my_table;
RENOMEAR my_table TO old_table, new_table TO my_table;
DROP old_table;
Ou mantenha old_table para uma reversão, se necessário.
Isso funcionará, mas as chaves estrangeiras não serão movidas. Você teria que adicioná-los novamente a minha_tabela mais tarde; também as chaves estrangeiras em outras tabelas que fazem referência a minha_tabela terão que ser corrigidas (apontadas para a nova minha_tabela).
Boa sorte...
fonte
Você pode usar este script, usar sua coluna, esquema e nome de tabela
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;
fonte
Sei que esse tópico está bem antigo agora, mas eu estava tendo o mesmo problema. Esta era minha solução básica usando o MySQL Workbench, mas funcionou bem ...
x
DROPa
;quaisquer tabelas que tinham a tabela agora não têm nenhuma tabela que não tivesse mostrado um erro nos logs
então você pode encontrar / substituir 'drop
a
' alterá-lo para 'ADD COLUMNb
INT NULL' etc e executar tudo novamente ....um pouco desajeitado, mas finalmente você obtém o resultado final e pode controlar / monitorar todo o processo e lembrar de salvar seus scripts sql caso precise deles novamente.
fonte