Menu

ATTACH DATABASE w SQLite: zapytania do wielu plików

Jak ATTACH DATABASE pozwala otworzyć kilka plików SQLite w jednym połączeniu, wykonywać zapytania na nich wszystkich z prefiksami schematów i odłączyć je, gdy skończysz.

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

Jedno połączenie, wiele plików

Połączenie SQLite nie jest przywiązane do jednego pliku. Dzięki ATTACH DATABASE możesz otworzyć kolejne pliki .db obok tego, od którego zaczynasz, i odpytywać je wszystkie tak, jakby były schematami w jednej bazie. To najbliższy odpowiednik "wielu baz na jednym serwerze", jaki ma SQLite.

Podstawowa forma:

Plik archive.db zostanie utworzony, jeśli nie istnieje, tak samo jak główna baza. Od teraz w tej sesji wszystko z prefiksem archive. znajduje się w tym drugim pliku. Wszystko z prefiksem main. (lub bez prefiksu) znajduje się w oryginalnym.

Twoje połączenie zawsze ma dwa niejawne schematy: main (plik otwarty jako pierwszy) i temp (brudnopis na tabele tymczasowe). Dołączanie dodaje kolejne.

Składnia i rola aliasu

ATTACH DATABASE 'path/to/file.db' AS alias_name;

Alias to nazwa schematu, którą będziesz poprzedzać nazwy tabel. Działa lokalnie w bieżącym połączeniu: inne połączenie, które dołącza ten sam plik, może wybrać inny alias. Wybierz coś krótkiego i opisowego (archive, analytics, cache), bo będziesz to często wpisywać.

Kilka rzeczy wartych uwagi:

  • Ścieżka jest względna wobec katalogu roboczego procesu, chyba że jest bezwzględna.
  • Ciąg ':memory:' dołącza pod tym aliasem świeżą bazę w pamięci.
  • Alias nie może kolidować z main ani temp i nie może się powtarzać między dołączeniami.

Złączenia między bazami

To funkcja, dla której większość ludzi dołącza bazy. Gdy dwa pliki są w tym samym połączeniu, możesz łączyć ich tabele w jednym zapytaniu:

Planer zapytań traktuje oba schematy tak samo jak tabele w main. Indeksy na dołączonych tabelach są używane. EXPLAIN QUERY PLAN działa także na nich. Nie ma żadnej podróży przez sieć: oba pliki są otwarte w tym samym procesie.

To naprawdę przydaje się do oddzielania gorących danych od zimnych archiwów, rozdzielania plików na klientów (tenantów) albo pobierania danych referencyjnych z bazy słownikowej tylko do odczytu.

Dołączanie tylko do odczytu i w pamięci

Jeśli drugą bazę chcesz czytać, ale nigdy nie modyfikować (na przykład dostarczony zbiór danych referencyjnych), dołącz ją w trybie tylko do odczytu przez URI:

Forma URI wymaga, aby biblioteka SQLite miała włączone SQLITE_OPEN_URI (tak jest w CLI i w większości bibliotek dla języków programowania). Każde INSERT, UPDATE lub DELETE na ref.* zgłosi wtedy błąd, zanim dotknie pliku.

Dołączanie baz w pamięci jest równie wygodne do przygotowywania danych pośrednich:

scratch znika, gdy połączenie się zamyka. To jak temp, tylko że ty kontrolujesz czas życia.

Transakcje obejmują każdą dołączoną bazę

Jedno BEGIN/COMMIT obejmuje zapisy do main i do każdego dołączonego schematu. Albo zatwierdza się wszystko, albo wszystko jest wycofywane: atomowość jest zachowana między plikami:

Przenoszenie wierszy z tabeli roboczej do pliku archiwum to dokładnie ten rodzaj operacji, przy którym chcesz mieć taką gwarancję. Bez atomowości między plikami awaria w połowie zostawiłaby duplikaty albo, co gorsza, zgubione wiersze.

Jedno zastrzeżenie: gdy w transakcji zapisuje się do więcej niż jednej dołączonej bazy, SQLite używa ostrożniejszego protokołu zatwierdzania, który wymaga tymczasowego dziennika. Jest wolniejszy niż commit jednego pliku, ale wciąż bezpieczny.

Odłączanie

Gdy skończysz z dołączoną bazą, odłącz ją:

DETACH DATABASE archive;

Plik zostaje na dysku nietknięty, bo DETACH tylko zamyka uchwyt w bieżącym połączeniu. Dwa ograniczenia, o których warto pamiętać:

  • Nie możesz odłączyć main ani temp.
  • Nie możesz odłączyć bazy, która jest w trakcie transakcji albo ma otwarte instrukcje.

Jeśli zapomnisz odłączyć, świat się nie zawali: zamknięcie połączenia wszystko sprząta.

Limity i typowe błędy

Kilka praktycznych limitów, które warto znać:

  • Domyślny limit to 10 dołączonych baz na połączenie (plus main i temp). Maksimum ustawiane przy kompilacji to 125. Po przekroczeniu limitu zobaczysz too many attached databases - max 10.
  • Każdy dołączony plik używa własnej pamięci podręcznej stron. Dołączenie kilkunastu dużych baz nie jest za darmo: rośnie zużycie RAM.
  • Samo ATTACH nie może działać wewnątrz transakcji. Uruchom je przed BEGIN albo po COMMIT.

Kilka błędów, które prawdopodobnie spotkasz:

-- Plik nie istnieje, a katalog nie pozwala na zapis:
Error: unable to open database: 'missing/path.db'

-- Próba zapisu do bazy dołączonej tylko do odczytu:
Error: attempt to write a readonly database

-- Ten sam alias użyty dwa razy:
Error: database archive is already in use

Większość z nich jest oczywista, gdy się je przeczyta. Błąd "already in use" łapie wiele osób: ATTACH nie zastępuje istniejącego aliasu, najpierw trzeba zrobić DETACH.

Realistyczny wzorzec: podział na gorące i zimne dane

Składając wszystko razem: mały proces archiwizacji, który przenosi zamówienia starsze niż rok poza główną bazę:

Stare wiersze trafiają do archive.orders, a nowe zostają w main. Raporty, które potrzebują historii, mogą łączyć obie tabele. Codzienne zapytania do main.orders pozostają szybkie, bo tabela jest mniejsza. Jedno połączenie, dwa pliki, jedna transakcja.

Dalej: prepared statements

ATTACH polega na tym, żeby dać jednemu połączeniu dostęp do większej ilości danych. Kolejne tematy dotyczą tego, jak aplikacje rozmawiają z SQLite bezpiecznie i wydajnie, zaczynając od prepared statements, czyli podstawy wiązania parametrów i zapytań odpornych na wstrzykiwanie.

Najczęściej zadawane pytania

Co robi ATTACH DATABASE w SQLite?

ATTACH DATABASE 'file.db' AS alias otwiera drugi plik bazy SQLite w bieżącym połączeniu i nadaje mu nazwę schematu. Od tej chwili możesz odwoływać się do jego tabel jako alias.table_name i łączyć je z tabelami głównej bazy w jednym zapytaniu.

Ile baz danych SQLite może dołączyć jednocześnie?

Domyślnie SQLite pozwala na maksymalnie 10 dołączonych baz na połączenie, do tego schematy main i temp. Twardy limit to 125 i ustawia się go przy kompilacji przez SQLITE_MAX_ATTACHED. Gdy go przekroczysz, dostaniesz błąd too many attached databases.

Czy mogę w jednej instrukcji odpytywać kilka dołączonych baz SQLite?

Tak. Po dołączeniu poprzedź każdą tabelę nazwą jej schematu: SELECT * FROM main.users JOIN archive.orders ON .... Złączenia, podzapytania i INSERT ... SELECT działają między schematami. Transakcje też obejmują każdą dołączoną bazę, więc COMMIT jest atomowy dla wszystkich plików.

Jak odłączyć bazę SQLite?

Uruchom DETACH DATABASE alias. Plik zostaje na dysku nietknięty, bo DETACH tylko zamyka uchwyt w bieżącym połączeniu. Nie możesz odłączyć main ani temp ani bazy, która jest w trakcie transakcji.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ