Usando ALTER para soltar una columna si existe en MySQL
Pregunta
¿Cómo se puede usar ALTER para colocar una columna en una tabla MySQL si esa columna existe?
Sé que puedo usar ALTER TABLE my_table DROP COLUMN my_column
, pero eso arrojará un error si my_column
no existe. ¿Existe una sintaxis alternativa para descartar la columna condicionalmente?
Estoy usando MySQL versión 4.0.18.
Solución
Para MySQL, no hay ninguno: Solicitud de funciones de MySQL .
Permitir que esto sea una mala idea, de todos modos: IF EXISTS
indica que está ejecutando operaciones destructivas en una base de datos con (para usted) estructura desconocida. Puede haber situaciones en las que esto sea aceptable para el trabajo local rápido y sucio, pero si está tentado a ejecutar dicha declaración contra los datos de producción (en una migración, etc.), está jugando con fuego.
Pero si insiste, no es difícil simplemente verificar la existencia primero en el cliente, o detectar el error.
MariaDB también admite lo siguiente a partir de 10.0.2:
DROP [COLUMN] [IF EXISTS] col_name
i. e.
ALTER TABLE my_table DROP IF EXISTS my_column;
Pero podría decirse que es una mala idea confiar en una característica no estándar compatible con solo uno de varios tenedores de MySQL.
Otros consejos
No hay soporte de nivel de lenguaje para esto en MySQL. Aquí hay una solución alternativa que involucra metadatos de MySQL information_schema en 5.0+, pero no resolverá su problema en 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;
Escribí información más detallada en una publicación de blog .
Sé que este es un hilo antiguo, pero hay una manera simple de manejar este requisito sin usar procedimientos almacenados. Esto puede ayudar a alguien.
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 esto ayude a alguien, como lo hizo yo (después de muchas pruebas y errores).
Acabo de construir un procedimiento reutilizable que puede ayudar a hacer que DROP COLUMN
sea 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');
Ejemplo:
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
La respuesta de Chase Seibert funciona, pero agregaría que si tiene varios esquemas desea alterar el SELECCIONAR así:
select * from information_schema.columns where table_schema in (select schema()) and table_name=...
Me doy cuenta de que este hilo es bastante antiguo ahora, pero estaba teniendo el mismo problema. Esta fue mi solución muy básica usando MySQL Workbench, pero funcionó bien ...
- obtenga un nuevo editor sql y ejecute SHOW TABLES para obtener una lista de sus tablas
- seleccione todas las filas y elija copiar al portapapeles (sin comillas) en el menú contextual
- pegue la lista de nombres en otra pestaña del editor
- escriba su consulta, es decir, ALTER TABLE
x
DROPa
; - copie y pegue, de modo que termine con una consulta separada para cada tabla
- Alternar si el banco de trabajo debe detenerse cuando se produce un error
- Pulse ejecutar y mire a través del registro de salida
cualquier tabla que tenía la tabla ahora no tiene cualquier tabla que no haya mostrado un error en los registros
entonces puede encontrar / reemplazar 'soltar
un poco torpe, pero al fin obtienes el resultado final y puedes controlar / monitorear todo el proceso y recuerda guardar tus scripts sql en caso de que los necesites nuevamente.