Los esquemas cambian. SQLite te deja cambiarlos — casi siempre.
Tarde o temprano vas a querer renombrar una tabla, añadir una columna, eliminar otra o reestructurarla por completo. SQLite cubre los casos más comunes directamente con DROP TABLE y ALTER TABLE, y para todo lo demás ofrece un patrón documentado que sirve como solución alternativa.
El detalle: el ALTER TABLE de SQLite es bastante más limitado que el de Postgres o MySQL. Saber qué puede y qué no puede hacer — y conocer el patrón de reconstrucción para lo que no puede — es prácticamente todo el truco.
DROP TABLE: eliminar una tabla y todo lo que cuelga de ella
DROP TABLE elimina la tabla, sus filas, sus índices y cualquier trigger definido sobre ella. No hay vuelta atrás:
La tabla ya no existe. Si intentas consultarla ahora, obtendrás el error no such table: scratch.
Cuando no tengas la certeza de que la tabla exista —algo habitual en scripts de inicialización—, añade IF EXISTS para que la sentencia no haga nada si no la encuentra:
Sin IF EXISTS, el segundo DROP lanzaría un error. Con esa cláusula, ambos se ejecutan sin problema.
Las claves foráneas pueden bloquear un DROP
Si tienes activada la verificación de claves foráneas (PRAGMA foreign_keys = ON;) y otra tabla hace referencia a la que vas a eliminar, el DROP falla:
sqlite> PRAGMA foreign_keys = ON;
sqlite> DROP TABLE users;
Runtime error: FOREIGN KEY constraint failed
Tienes varias salidas: eliminar primero la tabla que referencia, borrar las filas que apuntan a ella, o definir la clave foránea con ON DELETE CASCADE desde el momento en que la creas. SQLite no va a romper en silencio la integridad referencial por ti.
ALTER TABLE en SQLite: las cuatro operaciones disponibles
El ALTER TABLE de SQLite admite exactamente cuatro operaciones:
Cada una de estas instrucciones se ejecuta como una sola sentencia. Las dos primeras prácticamente no cuestan nada: solo actualizan el esquema. ADD COLUMN también es rápido, ya que SQLite no reescribe la tabla, sino que se limita a registrar la definición de la nueva columna. DROP COLUMN, en cambio, es más pesado: SQLite tiene que reescribir todas las filas para eliminar físicamente los datos de esa columna.
ALTER TABLE ADD COLUMN con valor por defecto
Al añadir una columna nueva a una tabla existente, todas las filas arrancan con NULL, a menos que indiques un valor por defecto:
Las dos filas existentes quedan con 'active'. Eso sí: el valor por defecto tiene que ser una constante. SQLite no te deja usar CURRENT_TIMESTAMP ni ninguna otra expresión no constante como default en ADD COLUMN, porque necesita un valor que pueda aplicar a todas las filas existentes sin evaluarlo fila por fila.
Si lo que quieres es un NOT NULL sin valor por defecto, vas a tener que añadir la columna como nullable, rellenarla con un UPDATE y luego reconstruir la tabla para añadir la restricción. Lo cual nos lleva directo a las limitaciones.
Limitaciones de ALTER TABLE en SQLite
Cosas que funcionan en Postgres o MySQL, pero no en SQLite:
- Cambiar el tipo de una columna (
ALTER COLUMN ... TYPE ...). - Cambiar el valor por defecto de una columna sobre la marcha.
- Añadir o quitar
NOT NULL,CHECK,UNIQUEoPRIMARY KEYen una columna ya existente. - Añadir una clave foránea a una columna existente.
- Reordenar columnas.
Cualquiera de estas operaciones te lanza un error de sintaxis. SQLite directamente no tiene cláusula ALTER COLUMN. Y la respuesta oficial es siempre la misma: reconstruir la tabla.
El patrón para reconstruir una tabla
Cuando ALTER TABLE se queda corto, la receta es: creas una tabla nueva con el esquema que quieres, copias los datos, eliminas la antigua y renombras la nueva para que ocupe su lugar. Envuélvelo todo en una transacción para que sea todo o nada:
Ahora users.age es un entero con una restricción CHECK y email quedó como NOT NULL. Los datos se vinieron con todo.
Algunas cosas que conviene tener presentes cuando hagas esto en producción:
- Desactiva las claves foráneas mientras dure la operación. Si otras tablas referencian a la tuya, ejecuta
PRAGMA foreign_keys = OFF;antes de la transacción yPRAGMA foreign_keys = ON;al terminar. Si no, elDROP TABLEfallará. Ojo: este pragma no se puede modificar dentro de una transacción, así que tienes que hacerlo por fuera. - Recrea los índices y triggers. Al borrar la tabla vieja también se eliminan sus índices y triggers. Vuelve a crearlos sobre la tabla nueva después del renombrado.
- Revisa las vistas. Las vistas que referencian la tabla siguen apuntando al nombre viejo en su SQL almacenado. Reconstruye las que dependan de columnas que hayan cambiado.
El patrón de reconstruir tabla en SQLite es verboso, pero confiable. Es justo lo que hacen herramientas de migraciones como Alembic o Rails por debajo cuando trabajan contra SQLite.
Eliminar varias tablas en SQLite
No existe una sola sentencia para hacer sqlite drop table sobre varias tablas a la vez: tienes que ejecutar un DROP TABLE por cada una. Si quieres agruparlas, mételas dentro de una transacción:
Si las metes dentro de una transacción, o se ejecutan los tres DROP o no se ejecuta ninguno. Resulta útil cuando estás desmontando tablas relacionadas y la operación podría fallar a mitad por las claves foráneas.
Lo que te llevas
DROP TABLEelimina una tabla junto con sus índices y triggers. UsaIF EXISTSpara que tus scripts sean idempotentes.ALTER TABLEen SQLite solo hace cuatro cosas: renombrar la tabla, renombrar una columna, añadir una columna y eliminar una columna.- Para cualquier otra cosa —cambiar tipos, añadir constraints nuevos o claves foráneas a columnas ya existentes— toca reconstruir la tabla dentro de una transacción.
- Cuando reconstruyas, no pierdas de vista las claves foráneas, los índices, los triggers y las vistas. Esos no viajan con los datos automáticamente.
Lo que viene: meter datos en las tablas
Hasta aquí has dedicado un capítulo entero a las tablas y a las restricciones que les dan forma. Toca llenarlas. El siguiente capítulo arranca con INSERT, incluyendo la variante de inserción de varias filas, los valores por defecto y cómo gestiona SQLite las inserciones que chocan con tus constraints.
Preguntas frecuentes
¿Cómo se borra una tabla en SQLite?
Con DROP TABLE nombre_tabla;. Si añades IF EXISTS, la sentencia no falla cuando la tabla no existe: DROP TABLE IF EXISTS users;. Al borrar la tabla también se eliminan sus índices y triggers, y si tienes las claves foráneas activadas, el DROP fallará mientras otras tablas sigan referenciándola.
¿Qué cosas permite hacer ALTER TABLE en SQLite?
Cuatro, ni una más: RENAME TO (renombrar la tabla), RENAME COLUMN ... TO ... (renombrar una columna), ADD COLUMN (añadir una columna nueva al final) y DROP COLUMN (eliminar una columna, disponible desde SQLite 3.35). Lo que no puedes hacer es cambiar el tipo de una columna, modificar su valor por defecto sobre la marcha ni añadirle una restricción a una columna ya existente.
¿Cómo cambio el tipo o las restricciones de una columna en SQLite?
SQLite no lo permite directamente. La solución habitual es el patrón de reconstrucción: creas una tabla nueva con el esquema que quieres, haces INSERT INTO nueva SELECT ... FROM antigua, luego DROP TABLE antigua y por último ALTER TABLE nueva RENAME TO antigua. Envuélvelo todo en una transacción para que sea atómico y no te quedes a medias.