Menu

Import CSV do SQLite: wczytywanie danych przez .import i --csv

Jak zaimportować pliki CSV do SQLite poleceniem .import: nagłówki, istniejące tabele, własne separatory i najczęstsze błędy.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Import CSV działa w CLI, a nie w SQL

W dialekcie SQL używanym przez SQLite nie ma instrukcji IMPORT. Wczytywanie CSV to funkcja powłoki wiersza poleceń sqlite3: polecenie z kropką o nazwie .import. To ważna zmiana myślenia, jeśli znasz LOAD DATA INFILE z MySQL albo COPY z Postgresa: one działają po stronie serwera, a .import wykonuje za ciebie narzędzie klienckie, które czyta plik i w tle wysyła instrukcje INSERT.

Dlatego wszystko na tej stronie zakłada, że jesteś w powłoce sqlite3:

sqlite3 mydata.db

Jeśli zamiast tego musisz importować z kodu aplikacji (Python, Node, Go), wczytasz CSV w swoim języku i użyjesz sparametryzowanych instrukcji INSERT. Ten sposób omawiamy w rozdziale o integracji z aplikacjami. Tutaj skupiamy się na CLI.

Podstawowe .import

Najkrótsza droga: powiedz SQLite, że plik jest w formacie CSV, a potem wskaż .import plik i nazwę tabeli.

.mode csv
.import people.csv people

Dzieją się dwie różne rzeczy, zależnie od tego, czy people już istnieje:

  • Tabela nie istnieje: SQLite ją tworzy, biorąc pierwszy wiersz CSV jako nazwy kolumn. Każda kolumna dostaje powinowactwo TEXT.
  • Tabela istnieje: SQLite wstawia każdy wiersz pliku jako dane. Wiersz nagłówka, jeśli jest, staje się zwykłym wierszem.

Na tym drugim przypadku większość osób łapie się przy pierwszej próbie. Jeśli CSV ma nagłówek, a tabela już istnieje, musisz go jawnie pominąć.

Pomijanie nagłówka przy istniejącej tabeli

Użyj --skip 1, żeby .import zignorowało pierwsze N linii:

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

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

--csv to skrót od .mode csv obowiązujący tylko dla tego jednego polecenia, więc nie musisz osobno ustawiać trybu. --skip 1 pomija nagłówek. Pozostałe linie trafiają do people w kolejności kolumn.

Szybkie sprawdzenie po imporcie:

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

Kolejność kolumn w pliku musi odpowiadać kolejności kolumn w tabeli. Nie ma dopasowania po nagłówkach: .import po prostu przypisuje N-te pole do N-tej kolumny.

Niech SQLite utworzy tabelę za ciebie

Przy pracy eksploracyjnej najprościej całkiem pominąć CREATE TABLE i pozwolić .import zbudować tabelę na podstawie nagłówka:

.mode csv
.import sales.csv sales

.schema sales

.schema sales pokaże coś takiego:

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

Zwróć uwagę, że każda kolumna jest TEXT. To celowe: .import nie próbuje zgadywać typów. Jeśli chcesz, żeby amount było liczbą rzeczywistą, a ordered_at porządnym znacznikiem czasu, najpierw sam utwórz tabelę z właściwymi typami, a potem importuj z --skip 1. Powinowactwo typów w SQLite zamieni przy wstawianiu ciągi liczbowe na liczby całkowite i rzeczywiste.

Własne separatory: TSV, kreska pionowa, średnik

.mode csv używa przecinka. Dla plików rozdzielanych tabulatorami zmień tryb:

.mode tabs
.import data.tsv events

Dla innych separatorów użyj .separator po wybraniu trybu:

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

Jedna rzecz do zapamiętania: .mode csv stosuje zasady cudzysłowów z RFC 4180, więc pola z przecinkami lub znakami nowej linii w środku działają, o ile są poprawnie ujęte w ". .mode tabs to prostszy tryb, który dzieli tekst po znaku, bez obsługi cudzysłowów. Jeśli plik ma pola w cudzysłowach z separatorami w środku, zostań przy .mode csv i zmień separator.

Realistyczny przykład krok po kroku

Załóżmy, że orders.csv wygląda tak:

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

Zwróć uwagę, że wiersz 3 ma przecinek wewnątrz pola w cudzysłowie. Oto cała sesja:

W prawdziwej powłoce blok INSERT zastąpiłoby jedno .import --csv --skip 1 orders.csv orders. Pole "Chen, Wei" pozostaje nienaruszone, bo tryb CSV respektuje cudzysłowy. Dzięki typom kolumn amount staje się liczbą rzeczywistą, a order_id liczbą całkowitą.

Import w transakcji

.import wysyła jedno INSERT na wiersz. Przy kilku tysiącach wierszy to nie problem. Przy milionie jest to boleśnie wolne, chyba że opakujesz całość w transakcję, żeby SQLite nie zatwierdzał zmian po każdym wierszu:

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

Ta jedna zmiana potrafi skrócić import z kilku minut do kilku sekund. Jeśli coś się nie uda w trakcie importu, ROLLBACK cofa częściowo wczytane dane, co przydaje się też przy ponownych próbach.

Możesz jeszcze bardziej przyspieszyć import, usuwając indeksy przed nim i tworząc je ponownie po nim: utrzymywanie indeksu przy każdym wierszu sporo kosztuje.

Częste błędy i jak je naprawić

Error: expected N columns but found M: liczba pól w wierszu nie zgadza się z tabelą. Zwykle przyczyną jest:

  • Zbędny przecinek w polu bez cudzysłowów. Wyeksportuj plik ponownie z poprawnymi cudzysłowami CSV albo przełącz się na .mode csv (RFC 4180) zamiast .mode tabs.
  • Pusta linia na końcu pliku. Popraw plik albo pomysłowo użyj --skip.
  • Tabela ma więcej kolumn niż CSV. Dodaj brakujące kolumny do pliku albo wstaw dane do tabeli pośredniej o właściwym kształcie i skopiuj je do docelowej tabeli.

Nagłówek pojawia się jako dane: przy istniejącej tabeli zabrakło --skip 1. Usuń ten wiersz (DELETE FROM t WHERE rowid = 1) i uruchom import ponownie z flagą.

Liczby zapisane jako tekst: .import samo utworzyło tabelę, więc każda kolumna jest TEXT. Usuń tabelę, zdefiniuj ją jawnie z kolumnami INTEGER/REAL i zaimportuj ponownie.

Error: no such file: ścieżka jest względna wobec miejsca, z którego uruchomiono sqlite3, a nie wobec pliku bazy. Użyj ścieżki bezwzględnej albo przejdź przez cd do właściwego katalogu przed otwarciem powłoki.

CLI wypisuje przy błędach numery linii, co jest najszybszym sposobem na znalezienie problematycznego wiersza w dużym pliku.

Krótkie podsumowanie

  • .import to polecenie z kropką w CLI, a nie SQL. Uruchamiaj je w powłoce sqlite3.
  • Użyj --csv, żeby poprawnie obsłużyć cudzysłowy, i --skip 1, żeby zignorować wiersz nagłówka.
  • Jeśli tabela nie istnieje, .import tworzy ją na podstawie nagłówka, ale każda kolumna będzie TEXT. Żeby mieć właściwe typy, utwórz tabelę sam.
  • Duże importy opakuj w BEGIN/COMMIT, żeby uniknąć osobnej transakcji dla każdego wiersza.
  • Kolejność kolumn w pliku musi odpowiadać kolejności kolumn w tabeli.

Dalej: eksport danych na zewnątrz

Import to tylko połowa historii. Ta sama powłoka potrafi zrzucić wyniki zapytań albo całe tabele z powrotem do CSV, JSON lub SQL, co przydaje się przy kopiach zapasowych, potokach danych i przekazywaniu danych do innych narzędzi. O tym w części o eksporcie danych.

Najczęściej zadawane pytania

Jak zaimportować plik CSV do SQLite?

Otwórz bazę w CLI sqlite3, przełącz się w tryb CSV przez .mode csv, a potem uruchom .import data.csv table_name. Jeśli tabela jeszcze nie istnieje, SQLite ją tworzy, biorąc pierwszy wiersz pliku jako nazwy kolumn. Jeśli istnieje, każdy wiersz pliku zostaje wstawiony jako dane, więc zwykle potrzebujesz .import --skip 1, żeby pominąć nagłówek.

Jak zaimportować CSV z nagłówkiem do istniejącej tabeli SQLite?

Użyj .import --csv --skip 1 data.csv table_name. Flaga --skip 1 każe SQLite zignorować pierwszą linię, żeby nagłówek nie stał się wierszem danych. Bez niej skończysz z wierszem zawierającym dosłowne nazwy kolumn.

Dlaczego import CSV do SQLite kończy się błędem 'expected N columns but found M'?

Plik ma wiersze z inną liczbą kolumn niż tabela, zwykle przez przecinki w środku pól, niezabezpieczone cudzysłowy albo pustą linię na końcu. Użyj .mode csv (lub --csv) zamiast .mode tabs, żeby SQLite obsługiwał cudzysłowy zgodnie z RFC 4180, i sprawdź plik w edytorze tekstu pod kątem zbędnych separatorów. CLI wypisuje numer problematycznej linii, co jest najszybszym sposobem na znalezienie złego wiersza.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ