CSV to SQL
Generera SQL INSERT-satser från CSV-data
CSV-indata
SQL-utdata
Vad är CSV till SQL-konvertering?
CSV till SQL-konvertering omvandlar kommaseparerade värden till Structured Query Language-satser som en relationsdatabas kan köra. Det vanligaste resultatet är ett par: en CREATE TABLE-sats som definierar kolumnerna, och en eller flera INSERT INTO-satser som fyller kolumnerna med raderna från CSV-filen.
CSV-filer följer RFC 4180-specifikationen. Varje rad är en post, fält separeras av ett avgränsartecken (vanligtvis ett kommatecken) och fält som innehåller avgränsartecknet eller radbrytningar omges av dubbla citattecken. SQL är å andra sidan standardspråket för att hantera data i system som PostgreSQL, MySQL, SQLite och SQL Server. Att konvertera mellan dessa två format är en av de vanligaste dataimportuppgifterna inom mjukvaruutveckling.
En korrekt CSV-till-SQL-konverterare hanterar citering, undantar enkla citattecken i värden (fördubblar dem till '' enligt SQL-standarden), mappar kolumnrubriker till giltiga SQL-identifierare och kan valfritt härleda datatyper. Utöver grundläggande undantagshantering normaliserar en bra konverterare rubriknamn (ersätter mellanslag och bindestreck med understreck) och omsluter utdatan i ett transaktionsblock, så att ett importmisslyckande återställs rent i stället för att lämna partiella data i tabellen. Utan en konverterare är det tidskrävande och felbenäget att skriva INSERT-satser för hand, även för ett par hundra rader.
Varför använda en CSV till SQL-konverterare?
Att skriva SQL INSERT-satser för hand från kalkylbladsdata är omständligt och inbjuder till syntaxfel. En konverterare automatiserar de repetitiva delarna så att du kan fokusera på schemadesign och datavalidering.
Användningsområden för CSV till SQL
Referens för SQL-datatyper
Vid konvertering av CSV till SQL används TEXT som standardtyp för alla kolumner eftersom CSV saknar typmetadata. Om du känner till kolumntyperna kan du ersätta TEXT i CREATE TABLE-utdatan. Den här tabellen visar de vanligaste SQL-typerna och när du bör använda respektive typ.
| Typ | Används för | Anteckningar |
|---|---|---|
| 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 |
Jämförelse av SQL-dialekter
SQL-syntaxen varierar mellan databasmotorer. De genererade INSERT-satserna använder standard-SQL som fungerar i de flesta system, men vissa funktioner skiljer sig åt. Den här tabellen sammanfattar de skillnader som är viktigast vid import av CSV-data.
| Funktion | 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: Att välja importmetod
För små till medelstora datamängder (under 10 000 rader) fungerar INSERT-satser bra och är portabla till alla SQL-databaser. För stora importer erbjuder databaser massinläsningskommandon som kringgår SQL-tolkaren helt.
Kodexempel
Dessa exempel visar hur man konverterar CSV till SQL INSERT-satser i olika programmeringsspråk. Varje exempel hanterar undantagshantering av enkla citattecken och rensning av kolumnnamn.
// 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;"