Menu

Importar CSV en SQLite con .import y --csv

Cómo importar archivos CSV a SQLite con el comando .import: cabeceras, tablas existentes, separadores personalizados y los errores más típicos al cargar datos.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

La importación de CSV vive en la CLI, no en SQL

En el dialecto SQL de SQLite no existe ninguna sentencia IMPORT. La carga de CSV es una funcionalidad del shell de línea de comandos sqlite3: un dot-command llamado .import. Si vienes de LOAD DATA INFILE de MySQL o de COPY de Postgres, conviene hacer el chip: aquellos se ejecutan en el servidor, mientras que .import corre en el cliente, lee el archivo por ti y emite las sentencias INSERT por debajo.

Por eso, todo lo que veremos en esta página da por hecho que estás dentro del shell de sqlite3:

sqlite3 mydata.db

Si necesitas importar desde el código de tu aplicación —Python, Node, Go—, tendrás que leer el CSV en tu lenguaje y usar sentencias INSERT parametrizadas. Ese enfoque lo veremos en el capítulo dedicado a la integración con aplicaciones. Aquí nos vamos a centrar en la CLI.

El comando .import básico

La vía más corta: dile a SQLite que el archivo es CSV y luego apunta .import al archivo y al nombre de la tabla.

.mode csv
.import people.csv people

Pueden pasar dos cosas según si la tabla people ya existe o no:

  • La tabla no existe — SQLite la crea usando la primera fila del CSV como nombres de columna. Todas las columnas quedan con afinidad TEXT.
  • La tabla ya existe — SQLite inserta todas las filas del archivo como datos. La fila de cabecera, si la hay, termina convertida en un registro más.

Ese segundo caso es donde casi todo el mundo tropieza la primera vez. Si tu CSV trae cabecera y la tabla ya existe, tienes que saltarla de forma explícita.

Saltar la cabecera del CSV al importar a una tabla existente

Usa --skip 1 para indicarle a .import que ignore las primeras N líneas:

CREATE TABLE people (
    name TEXT,
    age  INTEGER,
    city TEXT
);

.import --csv --skip 1 people.csv people

--csv es la forma corta de .mode csv aplicada solo a este comando, así que no hace falta cambiar el modo por separado. --skip 1 descarta la cabecera. El resto de líneas se insertan en people siguiendo el orden de las columnas.

Una comprobación rápida después de importar:

SELECT count(*) FROM people;
SELECT * FROM people LIMIT 5;

El orden de las columnas en el archivo debe coincidir con el orden de las columnas en la tabla. No hay un mapeo basado en la cabecera: .import simplemente alinea el campo N con la columna N.

Dejar que SQLite cree la tabla por ti

Para trabajo exploratorio, lo más cómodo es saltarte el CREATE TABLE y dejar que .import arme la tabla a partir de la cabecera:

.mode csv
.import sales.csv sales

.schema sales

.schema sales mostrará algo parecido a esto:

CREATE TABLE sales(
  "order_id" TEXT,
  "amount" TEXT,
  "ordered_at" TEXT
);

Fíjate en que todas las columnas son TEXT. Es a propósito: .import no intenta inferir tipos. Si quieres que amount sea un número real y ordered_at una marca de tiempo como Dios manda, crea tú mismo la tabla con los tipos correctos y luego importa con --skip 1. La afinidad de tipos de SQLite se encarga de convertir las cadenas numéricas en enteros y reales al insertarlas.

Separadores personalizados: TSV, pipe y punto y coma

.mode csv usa la coma. Si tu archivo está separado por tabulaciones, cambia de modo:

.mode tabs
.import data.tsv events

Para otros separadores, usa .separator después de elegir un modo:

.mode csv
.separator "|"
.import pipe_data.txt events

Algo importante a tener en cuenta: .mode csv sigue las reglas de comillas del RFC 4180, así que los campos con comas o saltos de línea dentro funcionan bien siempre que estén correctamente entre comillas ". Por su parte, .mode tabs es un modo más simple que parte por un carácter y no maneja comillas. Si tu archivo tiene campos entrecomillados con separadores dentro, quédate en .mode csv y cambia el separador.

Un recorrido práctico

Supón que orders.csv tiene esta pinta:

order_id,customer,amount,ordered_at
1001,Ada,49.99,2026-01-12
1002,Boris,12.50,2026-01-13
1003,"Chen, Wei",199.00,2026-01-14

Fíjate en que la fila 3 tiene una coma dentro de un campo entrecomillado. Aquí va la sesión completa:

En un shell real, el bloque de INSERT se reemplazaría por un único .import --csv --skip 1 orders.csv orders. El campo "Chen, Wei" se conserva tal cual porque el modo CSV respeta las comillas. Además, amount queda como número real y order_id como entero gracias a los tipos definidos en las columnas.

Envolver la importación en una transacción

.import ejecuta un INSERT por cada fila. Para unos pocos miles de filas no hay problema, pero con un millón se vuelve dolorosamente lento a menos que envuelvas todo en una transacción para que SQLite no haga commit después de cada fila:

BEGIN;
.import --csv --skip 1 big_file.csv events
COMMIT;

Este pequeño cambio puede convertir una importación de varios minutos en cuestión de segundos. Si algo falla a mitad del proceso, ROLLBACK deshace la carga parcial, lo cual también viene de perlas para reintentos.

Puedes acelerar aún más las cosas eliminando los índices antes de importar y recreándolos al terminar: el mantenimiento de índices fila a fila pesa muchísimo.

Errores comunes al importar CSV en SQLite y cómo solucionarlos

Error: expected N columns but found M — el número de campos de una fila no coincide con el de la tabla. Suele deberse a:

  • Una coma suelta dentro de un campo sin comillas. Vuelve a exportar el archivo con un entrecomillado CSV correcto, o cambia a .mode csv (RFC 4180) en lugar de .mode tabs.
  • Una línea en blanco al final del archivo. Edita el archivo o usa --skip con algo de ingenio.
  • La tabla tiene más columnas que el CSV. O bien añades las columnas que faltan al archivo, o insertas en una tabla intermedia con la forma correcta y desde ahí copias a la tabla real.

La cabecera aparece como un registro más — se te olvidó poner --skip 1 al importar sobre una tabla existente. Borra esa fila (DELETE FROM t WHERE rowid = 1) y vuelve a ejecutar el comando con la opción.

Números guardados como cadenas — dejaste que .import creara la tabla, así que todas las columnas quedaron como TEXT. Elimina la tabla, créala a mano con columnas INTEGER/REAL donde corresponda y vuelve a importar.

Error: no such file — la ruta es relativa al directorio desde el que lanzaste sqlite3, no al archivo de la base de datos. Usa una ruta absoluta o haz cd a la carpeta correcta antes de abrir la shell.

La CLI muestra el número de línea en los errores, que es la forma más rápida de localizar la fila problemática en archivos grandes.

Resumen rápido

  • .import es un comando-punto de la CLI, no es SQL. Hay que ejecutarlo dentro de la shell sqlite3.
  • Usa --csv para que el entrecomillado se maneje bien, y --skip 1 para saltar la cabecera del CSV.
  • Si la tabla no existe, .import la crea a partir de la cabecera, pero todas las columnas quedarán como TEXT. Crea tú mismo la tabla si quieres tipos correctos.
  • Envuelve las importaciones grandes entre BEGIN y COMMIT para evitar una transacción por fila.
  • El orden de las columnas en el archivo debe coincidir con el orden de las columnas en la tabla.

Siguiente paso: exportar los datos

Importar es solo la mitad del camino. La misma shell sirve para volcar resultados de consultas o tablas enteras a CSV, JSON o SQL, algo muy útil para copias de seguridad, pipelines de datos y para pasarle información a otras herramientas. Lo veremos en la sección de exportación de datos.

Preguntas frecuentes

¿Cómo importo un archivo CSV en SQLite?

Abre la base de datos con la CLI sqlite3, activa el modo CSV con .mode csv y ejecuta .import data.csv nombre_tabla. Si la tabla todavía no existe, SQLite la crea usando la primera fila del archivo como nombres de columna. Si ya existe, todas las filas del archivo se insertan como datos, así que normalmente querrás usar .import --skip 1 para saltarte la cabecera.

¿Cómo importo un CSV con cabecera en una tabla SQLite que ya existe?

Usa .import --csv --skip 1 data.csv nombre_tabla. La opción --skip 1 le dice a SQLite que ignore la primera línea, así la fila de cabecera no acaba metida como un registro más. Si la omites, te encontrarás con una fila que contiene los nombres de columna como si fueran datos.

¿Por qué falla la importación de CSV con el error 'expected N columns but found M'?

El archivo tiene filas con un número de columnas distinto al de la tabla, normalmente por comas dentro de los campos, comillas mal escapadas o una línea vacía al final. Usa .mode csv (o --csv) en lugar de .mode tabs para que SQLite gestione el entrecomillado según RFC 4180, y revisa el archivo con un editor de texto buscando separadores sueltos. La CLI imprime el número de la línea problemática, que es la forma más rápida de localizar la fila defectuosa.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR