Menu

INSERT w SQLite: dodawanie wierszy, wstawianie masowe i OR IGNORE

Jak działa INSERT w SQLite: pojedyncze wiersze, wstawianie wielu wierszy, INSERT...SELECT, wartości domyślne i modyfikatory konfliktów OR IGNORE / OR REPLACE.

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

INSERT dodaje wiersze do tabeli

INSERT to instrukcja, którą wstawiasz nowe wiersze do tabeli. Jej kształt jest krótki i przewidywalny:

Trzy części, na które warto zwrócić uwagę:

  • INSERT INTO books: tabela docelowa.
  • (title, author, year): kolumny, dla których podajesz wartości.
  • VALUES (...): wartości, w tej samej kolejności co lista kolumn.

id nie ma na liście kolumn, więc SQLite przypisuje je automatycznie (to INTEGER PRIMARY KEY, który dostaje rowid). Każda pominięta kolumna dostaje wartość domyślną albo NULL, jeśli jej nie ma.

Zawsze podawaj listę kolumn

Możesz pominąć listę kolumn i podać wartości dla każdej kolumny w kolejności deklaracji:

-- Działa, ale jest kruche:
INSERT INTO books VALUES (NULL, 'Dune', 'Frank Herbert', 1965);

Nie rób tego. Gdy tylko ktoś doda kolumnę do books, każda taka instrukcja się zepsuje albo zacznie wstawiać wartości do niewłaściwej kolumny. Wypisz kolumny:

Jawne listy kolumn to forma dokumentacji: dzięki nim instrukcja jest czytelna sama w sobie, bez szukania definicji tabeli.

Wstawianie wielu wierszy

W jednej instrukcji możesz wstawić kilka wierszy, podając więcej krotek wartości:

To czytelniejsze niż trzy osobne instrukcje INSERT, a SQLite traktuje całość jako jedną instrukcję. Prawdziwy zysk wydajności przy masowym wczytywaniu daje jednak opakowanie wstawień w transakcję, o czym za chwilę.

Wstawianie masowe: opakuj je w transakcję

Domyślnie każde INSERT to osobna transakcja. SQLite wykonuje fsync na końcu każdej z nich i to właśnie spowalnia naiwne pętle, a nie same wstawienia.

Zgrupuj je:

Jeden fsync zamiast pięciu. Przy tysiącach wierszy różnica może sięgać dwóch albo trzech rzędów wielkości. Jeśli coś w środku się nie powiedzie, ROLLBACK cofa całą paczkę.

Ten wzorzec to przepis na wstawianie masowe. Stosuj go niezależnie od tego, czy wywołujesz SQLite z Pythona, Node czy Rusta: opakuj pętlę w BEGIN / COMMIT.

INSERT ... SELECT: kopiowanie z innej tabeli

Tabelę możesz wypełnić wynikiem zapytania zamiast dosłownymi wartościami:

Kolumny z SELECT są dopasowywane do listy kolumn w INSERT według pozycji. Nazwy nie muszą się zgadzać, liczy się kolejność. To standardowy sposób na archiwizowanie wierszy, budowanie tabel raportowych albo kopiowanie części danych podczas migracji.

DEFAULT VALUES i pominięte kolumny

Jeśli kolumna ma klauzulę DEFAULT, możesz pominąć ją na liście kolumn, a SQLite wstawi wartość domyślną:

created_at dostaje bieżący znacznik czasu, bo go nie podaliśmy. Jeśli chcesz wiersz złożony wyłącznie z wartości domyślnych (przydatny jako wiersz zastępczy), użyj formy DEFAULT VALUES:

Dwa nowe wiersze, oba z value = 0 i automatycznie przypisanymi identyfikatorami.

INSERT OR IGNORE: pomijanie duplikatów

Gdy wiersz naruszyłby ograniczenie UNIQUE lub PRIMARY KEY, domyślnie instrukcja jest przerywana z błędem:

Error: UNIQUE constraint failed: users.email

INSERT OR IGNORE zamienia to na „po cichu pomiń problematyczny wiersz”:

Zostają trzy wiersze. Duplikat jest odrzucany bez błędu. To idiomatyczny w SQLite sposób na „wstaw, jeśli nie istnieje” dla prostych danych startowych: bez osobnego SELECT do sprawdzania i bez obsługi wyjątków.

INSERT OR REPLACE: nadpisywanie duplikatów

INSERT OR REPLACE usuwa konfliktowy wiersz i wstawia w jego miejsce nowy:

Uważaj na jedną rzecz: REPLACE to DELETE + INSERT, a nie UPDATE. Jeśli na usunięty wiersz wskazywały klucze obce z ON DELETE CASCADE, te dzieci też zostaną usunięte. A każda kolumna, której nie podasz w nowym INSERT, wraca do wartości domyślnej, a nie zachowuje starej.

W większości przypadków „zaktualizuj, jeśli istnieje, wstaw, jeśli nie” potrzebujesz tak naprawdę prawdziwego upsertu z ON CONFLICT ... DO UPDATE. Omawia go osobna strona.

Krótkie podsumowanie

  • INSERT INTO table (cols) VALUES (...): podstawowa forma. Zawsze podawaj kolumny.
  • Wstawianie wielu wierszy używa krotek rozdzielonych przecinkami po VALUES.
  • Przy prawdziwie masowym wczytywaniu opakuj wstawienia w BEGIN / COMMIT.
  • INSERT INTO ... SELECT ... kopiuje wiersze z zapytania.
  • DEFAULT VALUES tworzy wiersz z samych wartości domyślnych, a pominięte kolumny też dostają swoje wartości domyślne.
  • INSERT OR IGNORE pomija konfliktowe wiersze, a INSERT OR REPLACE je nadpisuje (przez usunięcie i wstawienie).

Dalej: UPDATE

Wstawianie wierszy to połowa historii. Druga połowa to zmiana wierszy, które już istnieją: zwiększenie licznika, poprawienie literówki, oznaczenie zamówienia jako wysłanego. To UPDATE, a ono ma własny zestaw nawyków, które warto opanować (zwłaszcza klauzulę WHERE). O tym w następnej części.

Najczęściej zadawane pytania

Jak wstawić wiersz w SQLite?

Użyj INSERT INTO table (col1, col2) VALUES (val1, val2);. Podawanie listy kolumn jest opcjonalne, ale bardzo zalecane: instrukcja działa dalej, nawet gdy tabela dostanie później nową kolumnę. Bez listy kolumn musisz podać wartość dla każdej kolumny w kolejności deklaracji.

Jak wstawić wiele wierszy naraz w SQLite?

Po VALUES podaj kilka krotek w nawiasach, rozdzielonych przecinkami: INSERT INTO t (a, b) VALUES (1, 2), (3, 4), (5, 6);. Przy prawdziwie masowym wczytywaniu (tysiące wierszy) opakuj wstawienia w jedną transakcję przez BEGIN i COMMIT: to ona daje przyspieszenie, a nie sama składnia wielu wierszy.

Co robi INSERT OR IGNORE w SQLite?

INSERT OR IGNORE pomija wiersze, które naruszyłyby ograniczenie UNIQUE, PRIMARY KEY lub NOT NULL, zamiast zgłaszać błąd. Konfliktowy wiersz jest po cichu odrzucany, a reszta instrukcji wykonuje się dalej. Używaj go, gdy chcesz zachowania „wstaw, jeśli jeszcze nie ma” bez osobnego sprawdzania istnienia.

Dlaczego przy INSERT dostaję 'UNIQUE constraint failed'?

SQLite znalazł istniejący wiersz z tą samą wartością w kolumnie UNIQUE lub PRIMARY KEY. Albo wartość naprawdę jest duplikatem, albo uruchamiasz ponownie skrypt z danymi startowymi. Przejdź na INSERT OR IGNORE, żeby pomijać duplikaty, na INSERT OR REPLACE, żeby je nadpisywać, albo użyj ON CONFLICT ... DO UPDATE (upsert), żeby mieć dokładniejszą kontrolę.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ