CSV a SQL
Genera sentencias SQL INSERT a partir de datos CSV
Entrada CSV
Salida SQL
¿Qué es la conversión de CSV a SQL?
La conversión de CSV a SQL transforma valores separados por comas en sentencias del Lenguaje de Consulta Estructurado que una base de datos relacional puede ejecutar. El resultado más habitual es un par de sentencias: CREATE TABLE, que define las columnas, y una o varias sentencias INSERT INTO, que rellenan esas columnas con las filas del archivo CSV.
Los archivos CSV siguen la especificación RFC 4180. Cada línea es un registro, los campos están separados por un delimitador (normalmente una coma) y los campos que contienen el delimitador o saltos de línea van entre comillas dobles. SQL, por su parte, es el lenguaje estándar para gestionar datos en sistemas como PostgreSQL, MySQL, SQLite y SQL Server. Convertir entre estos dos formatos es una de las tareas de importación de datos más frecuentes en el desarrollo de software.
Un convertidor CSV a SQL adecuado gestiona las comillas, escapa las comillas simples dentro de los valores (duplicándolas como '' según el estándar SQL), asigna las cabeceras de columna a identificadores SQL válidos y puede inferir tipos de datos de forma opcional. Más allá del escape básico, un buen convertidor normaliza los nombres de cabecera (reemplazando espacios y guiones por guiones bajos) y envuelve la salida en un bloque de transacción, de modo que un fallo en la importación deshace los cambios sin dejar datos parciales en la tabla. Sin un convertidor, escribir sentencias INSERT a mano para varios cientos de filas es lento y propenso a errores.
¿Por qué usar un convertidor de CSV a SQL?
Escribir sentencias SQL INSERT a mano a partir de datos de una hoja de cálculo es tedioso y propenso a errores de sintaxis. Un convertidor automatiza las partes repetitivas para que puedas concentrarte en el diseño del esquema y la validación de datos.
Casos de uso de CSV a SQL
Referencia de tipos de datos SQL
Al convertir CSV a SQL, cada columna tiene TEXT como tipo predeterminado porque CSV no tiene metadatos de tipo. Si conoces los tipos de las columnas, puedes reemplazar TEXT en la salida de CREATE TABLE. Esta tabla muestra los tipos SQL más comunes y cuándo usar cada uno.
| Tipo | Usado para | Notas |
|---|---|---|
| TEXT / VARCHAR | Strings, mixed content | Default safe choice; works in every SQL dialect |
| INTEGER / INT | Whole numbers (age, count, ID) | Use when column contains only digits with no decimals |
| REAL / FLOAT | Decimal numbers (price, rate) | Needed for columns with dots like 19.99 or 3.14 |
| DATE | ISO 8601 dates (2024-01-15) | Requires consistent formatting; varies by database |
| BOOLEAN | true/false, 1/0, yes/no | MySQL uses TINYINT(1); PostgreSQL has native BOOL |
| NUMERIC / DECIMAL | Exact precision (currency) | Specify scale: DECIMAL(10,2) for money columns |
| BLOB / BYTEA | Binary data | Rarely needed in CSV imports; use for hex-encoded fields |
Comparación de dialectos SQL
La sintaxis SQL varía según el motor de base de datos. Las sentencias INSERT generadas usan SQL estándar que funciona en la mayoría de los sistemas, pero ciertas características difieren. Esta tabla resume las diferencias más relevantes al importar datos CSV.
| Característica | PostgreSQL | MySQL | SQLite | SQL Server |
|---|---|---|---|---|
| Identifier quoting | "col" | `col` | "col" | [col] |
| String escape | '' | '' or \' | '' | '' |
| INSERT syntax | INSERT INTO | INSERT INTO | INSERT INTO | INSERT INTO |
| Batch INSERT | VALUES (),()… | VALUES (),()… | VALUES (),()… | max 1000 rows |
| Auto-increment | SERIAL | AUTO_INCREMENT | AUTOINCREMENT | IDENTITY(1,1) |
| Upsert / merge | ON CONFLICT | ON DUPLICATE KEY | ON CONFLICT | MERGE |
| NULL handling | IS NULL | IS NULL / <=> | IS NULL | IS NULL |
| COPY from CSV | COPY … FROM | LOAD DATA INFILE | .import | BULK INSERT |
INSERT vs COPY: elegir un método de importación
Para conjuntos de datos pequeños o medianos (menos de 10.000 filas), las sentencias INSERT funcionan bien y son portables entre cualquier base de datos SQL. Para importaciones grandes, las bases de datos ofrecen comandos de carga masiva que omiten el analizador SQL por completo.
Ejemplos de código
Estos ejemplos muestran cómo convertir CSV a sentencias SQL INSERT en distintos lenguajes. Cada uno gestiona el escape de comillas simples y el saneamiento de nombres de columna.
// CSV → SQL INSERT statements
const csv = `name,age,city
Alice,30,Berlin
Bob,25,Tokyo`
function csvToSql(csv, table = 'data') {
const rows = csv.trim().split('\n').map(r => r.split(','))
const [headers, ...data] = rows
const cols = headers.map(h => h.trim().toLowerCase().replace(/\s+/g, '_'))
const values = data.map(row =>
' (' + row.map(v => `'${v.replace(/'/g, "''").trim()}'`).join(', ') + ')'
)
return `INSERT INTO ${table} (${cols.join(', ')}) VALUES
${values.join(',\n')};`
}
console.log(csvToSql(csv, 'users'))
// → INSERT INTO users (name, age, city) VALUES
// ('Alice', '30', 'Berlin'),
// ('Bob', '25', 'Tokyo');import csv
import io
csv_string = """name,age,city
Alice,30,Berlin
Bob,25,Tokyo"""
reader = csv.reader(io.StringIO(csv_string))
headers = [h.strip().lower().replace(' ', '_') for h in next(reader)]
table = 'users'
rows = list(reader)
# CREATE TABLE
col_defs = ', '.join(f'{h} TEXT' for h in headers)
print(f'CREATE TABLE {table} ({col_defs});')
# → CREATE TABLE users (name TEXT, age TEXT, city TEXT);
# INSERT statements
for row in rows:
vals = ', '.join(f"'{v.replace(chr(39), chr(39)*2)}'" for v in row)
print(f"INSERT INTO {table} ({', '.join(headers)}) VALUES ({vals});")
# → INSERT INTO users (name, age, city) VALUES ('Alice', '30', 'Berlin');
# → INSERT INTO users (name, age, city) VALUES ('Bob', '25', 'Tokyo');package main
import (
"encoding/csv"
"fmt"
"strings"
)
func csvToSQL(data, table string) string {
r := csv.NewReader(strings.NewReader(data))
records, _ := r.ReadAll()
if len(records) < 2 {
return ""
}
headers := records[0]
var vals []string
for _, row := range records[1:] {
escaped := make([]string, len(row))
for i, v := range row {
escaped[i] = "'" + strings.ReplaceAll(v, "'", "''") + "'"
}
vals = append(vals, " ("+strings.Join(escaped, ", ")+")")
}
return fmt.Sprintf("INSERT INTO %s (%s) VALUES\n%s;",
table, strings.Join(headers, ", "), strings.Join(vals, ",\n"))
}
func main() {
csv := "name,age,city\nAlice,30,Berlin\nBob,25,Tokyo"
fmt.Println(csvToSQL(csv, "users"))
// → INSERT INTO users (name, age, city) VALUES
// ('Alice', '30', 'Berlin'),
// ('Bob', '25', 'Tokyo');
}# SQLite: import CSV directly into a table sqlite3 mydb.db <<EOF .mode csv .import data.csv users SELECT * FROM users LIMIT 5; EOF # PostgreSQL: COPY from CSV file (server-side) psql -c "COPY users FROM '/path/to/data.csv' WITH (FORMAT csv, HEADER true);" # PostgreSQL: \copy from CSV (client-side, no superuser needed) psql -c "\copy users FROM 'data.csv' WITH (FORMAT csv, HEADER true);" # MySQL: LOAD DATA from CSV mysql -e "LOAD DATA INFILE '/path/to/data.csv' INTO TABLE users FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS;"