Error SQL · DDL y migraciones

DROP COLUMN falla: la columna todavía tiene dependencias

ALTER TABLE ... DROP COLUMN puede fallar aunque la columna exista y la sintaxis sea correcta. Antes de borrarla, el motor debe comprobar si índices, restricciones, vistas, triggers, columnas generadas u otros objetos todavía dependen de ella. La solución segura es inventariar esas dependencias y retirar o rediseñar cada una de forma consciente.

Lectura: 15–20 minALTER TABLEMigraciones

El síntoma: DROP COLUMN se detiene para proteger el esquema

Imagina que quieres retirar codigo_legacy de clientes. La columna ya no se usa en la aplicación, pero todavía participa en un índice, una vista o una regla del esquema:

Intento de migración
ALTER TABLE clientes
DROP COLUMN codigo_legacy;

El error no significa necesariamente que DROP COLUMN sea incorrecto. Significa que eliminar la columna dejaría una dependencia sin el objeto que necesita o cambiaría una estructura que el motor no puede descartar automáticamente.

La causa real: el esquema es una red de dependencias

Una columna puede formar parte de mucho más que una tabla. Antes de eliminarla, revisa al menos:

  • índices que la usan como clave o columna incluida;
  • PRIMARY KEY, UNIQUE, CHECK o FOREIGN KEY;
  • vistas que la seleccionan o filtran;
  • triggers y expresiones de columnas generadas;
  • procedimientos o código de aplicación que todavía esperan encontrarla.
Idea clave: primero retira el uso de la columna; después retira sus dependencias de esquema; solo entonces elimina la columna.

Ejemplo reproducible en SQLite

SQLite permite ver el problema de forma compacta. Si una columna aparece en un índice explícito, el esquema ya no se puede reconstruir correctamente al borrarla:

Dependencia que bloquea DROP COLUMN
CREATE TABLE demo_clientes (
  id INTEGER PRIMARY KEY,
  codigo_legacy TEXT,
  nombre TEXT NOT NULL
);

CREATE INDEX idx_demo_codigo
ON demo_clientes(codigo_legacy);

ALTER TABLE demo_clientes
DROP COLUMN codigo_legacy;

En una versión actual de SQLite, la última sentencia falla porque el índice idx_demo_codigo todavía referencia codigo_legacy. El motor intenta reconstruir el esquema y detecta que quedaría una referencia inválida.

Diagnóstico: identifica qué depende de la columna

  1. Confirma la columna exacta: tabla, esquema y nombre real.
  2. Lista restricciones e índices: no asumas que el nombre de una constraint coincide con la columna.
  3. Busca referencias externas: otras tablas, vistas, triggers y columnas generadas.
  4. Clasifica cada dependencia: ¿debe desaparecer, migrarse a otra columna o conservarse?
  5. Diseña el orden de la migración: retirar dependencias primero y la columna al final.

En producción, usa los catálogos del motor y el historial de migraciones para construir este inventario. No confíes solo en una búsqueda de texto del código: una constraint o un índice puede haber sido creado por una migración antigua.

Corrección: elimina la dependencia antes de la columna

En el ejemplo de SQLite, la secuencia segura es explícita:

Orden correcto
DROP INDEX idx_demo_codigo;

ALTER TABLE demo_clientes
DROP COLUMN codigo_legacy;

Si la dependencia es funcional —por ejemplo, una vista que todavía expone la columna— no basta con “hacer que el DDL pase”. Primero decide cómo debe quedar esa vista y modifícala o retírala. La migración debe conservar la intención del sistema, no solo evitar un mensaje de error.

Qué cambia entre motores

PostgreSQL

DROP COLUMN elimina automáticamente índices y constraints de la propia tabla que involucran la columna. Si existen objetos externos dependientes —por ejemplo, una vista o una foreign key desde otra tabla— la operación se rechaza por defecto. CASCADE autoriza a PostgreSQL a eliminar también objetos dependientes.

No uses CASCADE como atajo. Antes de ejecutarlo, identifica exactamente qué objetos desaparecerán. Una migración que “funciona” pero elimina una vista necesaria sigue siendo una migración incorrecta.

SQL Server

Una columna no puede eliminarse mientras participe en determinados índices, CHECK, FOREIGN KEY, UNIQUE, PRIMARY KEY, valores predeterminados asociados u otras dependencias documentadas. Debes quitar primero esas dependencias y luego ejecutar DROP COLUMN.

SQLite

SQLite rechaza DROP COLUMN si la columna es PRIMARY KEY/UNIQUE o todavía aparece en otra parte del esquema: índices, índices parciales, CHECK, foreign keys, columnas generadas, triggers o vistas. La operación solo termina si el esquema completo puede seguir analizándose sin esa columna.

MySQL

MySQL elimina una columna de los índices en los que participa y puede eliminar el índice si ya no queda ninguna columna en él. Pero no todas las dependencias se resuelven igual: claves foráneas y columnas generadas pueden exigir retirar o redefinir primero la relación. Revisa SHOW CREATE TABLE y el catálogo antes de asumir qué desaparecerá automáticamente.

Una migración segura en cuatro etapas

  1. Deja de escribir la columna: despliega primero código que ya no dependa de ella.
  2. Deja de leerla: comprueba vistas, reportes, consultas y procesos externos.
  3. Retira dependencias: índices, constraints, triggers o columnas generadas que ya no tengan sentido.
  4. Elimina la columna: ejecuta DROP COLUMN como último paso y verifica el esquema resultante.

Separar estas etapas reduce el riesgo de desplegar una aplicación nueva y una migración destructiva en el mismo instante. En tablas grandes, además, revisa el coste y los bloqueos que la operación puede requerir en tu motor.

Errores frecuentes

  • Ejecutar CASCADE sin inventario: puede retirar objetos que sí eran necesarios.
  • Eliminar una constraint y olvidar el uso en la aplicación: el DDL pasa, pero el despliegue falla después.
  • Confundir índice con foreign key: no son la misma dependencia ni se eliminan con la misma sentencia.
  • Asumir que todos los motores hacen lo mismo: el orden y los objetos que se descartan automáticamente varían.
  • Probar solo sobre una tabla vacía: no revela dependencias del esquema real ni el coste operativo de una tabla grande.

Práctica correctiva: inventaría antes de borrar

Intermedia · DDL

Encuentra qué bloquea la retirada de codigo_legacy

Recibes un inventario simplificado de dependencias. Devuelve el tipo y el objeto de las dependencias que todavía usan codigo_legacy.

Criterio de éxito: deben aparecer idx_clientes_codigo y trg_clientes_audit.

Qué debes recordar

  • DROP COLUMN puede fallar por dependencias aunque la sintaxis sea correcta.
  • Inventaría índices, constraints, vistas, triggers y columnas generadas antes de borrar.
  • Retira o migra dependencias primero; elimina la columna al final.
  • CASCADE en PostgreSQL es explícito y potente: úsalo solo después de revisar sus efectos.
  • Las reglas cambian entre PostgreSQL, MySQL, SQL Server y SQLite; no copies una secuencia destructiva entre motores sin verificarla.

Conceptos relacionados

Fuentes técnicas

La explicación se contrastó con documentación primaria de cada motor: