Pergunta

Como pode ALTER ser usado para soltar uma coluna em uma tabela MySQL, se existe essa coluna?

Eu sei que posso usar ALTER TABLE my_table DROP COLUMN my_column, mas que irá lançar um erro se my_column não existe. Existe sintaxe alternativa para deixar cair a coluna condicionalmente?

Estou usando o MySQL versão 4.0.18.

Foi útil?

Solução

Para o MySQL, não há ninguém: MySQL Solicitação de recurso .

Permitir que esta é sem dúvida uma péssima idéia, de qualquer maneira: IF EXISTS indica que você está executando operações destrutivas em um banco de dados com (a você) estrutura desconhecida. Pode haver situações em que isso é aceitável para o trabalho local rápida e suja, mas se você está tentado a correr tal declaração em relação aos dados de produção (em uma migração etc.), você está brincando com fogo.

Mas se você insistir, não é difícil verificar simplesmente para a existência primeira no cliente, ou para capturar o erro.

MariaDB também suporta o seguinte começando com 10.0.2:

GOTA [COLUMN] [SE EXISTE] col_name

i. e.

ALTER TABLE my_table GOTA SE EXISTE my_column;

Mas é sem dúvida uma má idéia para contar com um recurso não-padrão apoiado por apenas um dos vários garfos de MySQL.

Outras dicas

Não há suporte nível de linguagem para isso no MySQL. Aqui está um-contornar envolvendo MySQL information_schema meta-dados em 5.0+, mas não vai resolver o seu problema em 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;

Eu escrevi algumas informações mais detalhadas em um blog .

Eu sei que esta é uma discussão antiga, mas há uma maneira simples de lidar com esse requisito sem o uso de 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, como aconteceu comigo (depois de muita tentativa e erro).

Acabei de construir um procedimento reutilizável que pode ajudar a fazer DROP COLUMN idempotent:

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

obras resposta de Chase Seibert, mas eu gostaria de acrescentar que, se você tem vários esquemas você quiser alterar o SELECT assim:

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

Eu percebo esta discussão é muito velho agora, mas eu estava tendo o mesmo problema. Esta foi a minha solução muito básico usando o MySQL Workbench, mas não funcionou bem ...

  1. obter um novo editor de sql e executar MOSTRAR tabelas para obter uma lista de suas tabelas
  2. selecione todas as linhas, e escolha cópia para área de transferência (sem aspas) no menu de contexto
  3. colar a lista de nomes em outra aba do editor
  4. escrever a sua consulta, ou seja, ALTER TABLE x GOTA a;
  5. fazer alguma copiar e colar, então você acaba com consulta separada para cada tabela
  6. Alternar se a bancada deve parar quando ocorre um erro
  7. Hit executar e olhar através do registro de saída

todas as tabelas que tiveram a mesa agora não tem todas as tabelas que não fez a vontade têm mostrado um erro nos logs

então você pode encontrar / substituir 'drop a' alterá-lo para 'ADD COLUMN b INT NULL' etc e executar a coisa toda de novo ....

um pouco desajeitado, mas finalmente obter o resultado final e você pode controlar / monitorar todo o processo e lembre-se para poupar sql roteiros no caso de você precisar deles novamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top