Przejdź do głównej zawartości

Claude Code pracuje z bazą danych, czytając pliki schematu, historię migracji i modele ORM projektu, a następnie przygotowuje zmiany schematu, pliki migracji, zapytania i skrypty seedujące zgodne z tymi konwencjami. Najważniejsze zastrzeżenie: Claude Code pisze pliki i sprawdza je na jednorazowej bazie, a migracje na współdzielonych środowiskach stosuje pipeline CI, nie agent.

Ta strona jest dla programistów, którzy używają Claude Code w terminalu i chcą dopuścić go do danych. Nowa funkcja potrzebuje trzech tabel, zapytanie raportowe trwa osiem sekund, a testy nie mają realistycznych danych. Claude Code przygotuje to wszystko w kilka minut. Ryzyko leży w kolejnym kroku: migracja, która blokuje tabelę z 20 milionami wierszy, albo agent, którego powłoka zna produkcyjny connection string.

  • Konfigurację sesji, w której Claude Code może zmieniać pliki schematu, ale nie sięga do współdzielonej bazy.
  • Prompty do skopiowania: projekt schematu, plik migracji, wolne zapytanie, zapytanie ORM, dane seedowe i mapa użycia tabel przygotowana przez subagenty.
  • Test na jednorazowej bazie (up, down, up, diff schematu), który dowodzi poprawności migracji bez czytania każdej linii SQL.
  • Bezobsługowy audyt claude -p, który zwraca JSON gotowy do użycia w jobie CI.
  • Typowe awarie przy pracy z bazą i sposób wyjścia z każdej z nich.

Błędy w bazie danych są drogie, bo dotyczą współdzielonego stanu. Trzy ustawienia trzymają Claude Code po bezpiecznej stronie tej granicy, a kolejność ma znaczenie: najpierw poświadczenia, potem reguły, na końcu kontekst.

Nie dawaj powłoce Claude Code poświadczeń do współdzielonych baz

Dział zatytułowany „Nie dawaj powłoce Claude Code poświadczeń do współdzielonych baz”

Claude Code uruchamia polecenia z twoim środowiskiem. W Claude Code v2.1.283 lub nowszym (oba kanały wydań na 2026-10-12) tryb auto jest startowym trybem uprawnień w interaktywnych sesjach terminalowych na obsługiwanych przez niego modelach, więc większość poleceń zatwierdza klasyfikator, a nie ty. Jeśli DATABASE_URL w tej powłoce wskazuje staging albo produkcję, jedno migrate deploy do niej dotrze. Jeśli nie masz jeszcze Claude Code, zacznij od instalacji; o tym, jak tryby uprawnień i sandboxing ograniczają sesję, przeczytasz na stronie uprawnienia i sandboxing.

Uruchamiaj Claude Code w powłoce, w której DATABASE_URL wskazuje lokalną albo jednorazową bazę. Wystarczy tymczasowy kontener Postgresa:

Okno terminala
# Terminal: bazy roboczej można się pozbyć w każdej chwili
docker run --rm -d --name pg-scratch -e POSTGRES_PASSWORD=scratch -p 55432:5432 postgres:17
export DATABASE_URL="postgresql://postgres:scratch@localhost:55432/postgres"
claude

Jeśli agent musi czytać staging, daj mu rolę tylko do odczytu przez serwer MCP, a nie connection string w powłoce. Strona serwery MCP dla baz danych opisuje tę rolę oraz instalację Postgres MCP Pro, DBHub, Supabase, Neon i MongoDB. Dla Postgres MCP Pro w Claude Code wpis na poziomie projektu wygląda tak:

Okno terminala
# Terminal, katalog główny repo: zapisuje .mcp.json; ${STAGING_DATABASE_URL} jest rozwijane z powłoki przy starcie
claude mcp add -s project postgres -e 'DATABASE_URI=${STAGING_DATABASE_URL}' \
-- uvx postgres-mcp --access-mode=restricted

--access-mode=restricted wykonuje zapytania w transakcjach tylko do odczytu z limitami czasu wykonania. Mimo to ustaw STAGING_DATABASE_URL na rolę tylko do odczytu, żeby ograniczenie egzekwowała baza, a nie tylko serwer. Postgres MCP Pro to pakiet z PyPI uruchamiany przez uvx; pakiet npm o nazwie postgres-mcp nie ma z nim nic wspólnego. Ostatnie wydanie na PyPI to 0.3.0 z 2025-05-16 (stan na 2026-09-26), więc zanim zespół się na nim oprze, sprawdź, czy projekt jest nadal rozwijany.

Zablokuj polecenia, które zapisują do współdzielonych baz

Dział zatytułowany „Zablokuj polecenia, które zapisują do współdzielonych baz”

Dodaj reguły deny do .claude/settings.json, żeby najczęstsze warianty polecenia „zastosuj tę migrację” nigdy nie zostały uruchomione w sesji. Dopasuj listę do swojego narzędzia migracji:

{
"permissions": {
"deny": [
"Bash(npx prisma migrate deploy *)",
"Bash(npx prisma db push *)",
"Bash(npx drizzle-kit push *)",
"Bash(npx drizzle-kit migrate *)"
],
"ask": [
"Bash(npx prisma migrate reset *)"
]
}
}

Zapisz konwencje bazodanowe w CLAUDE.md, żeby każda sesja zaczynała się od nich. Gdzie umieścić plik, opisuje system pamięci.

## Database
- Schema: prisma/schema.prisma. Migrations: prisma/migrations/ (never edit an applied one).
- Create a migration file only: `npx prisma migrate dev --create-only --name <change>`.
- The only database you may touch is $DATABASE_URL (local scratch). Never run `migrate deploy`.
- IDs are UUIDv7 strings, timestamps are `timestamptz` named created_at / updated_at.
- Every migration ships with a tested down path or a written reason why it is irreversible.

Tryb planowania pozwala Claude Code przeczytać schemat i zaproponować projekt bez edytowania czegokolwiek. Naciskaj Shift+Tab, aż wskaźnik pokaże tryb planowania, albo uruchom claude --permission-mode plan. Poproś o projekt i o zapytania, które ma obsługiwać, w jednym prompcie, bo indeksy wynikają z zapytań.

Zanim zatwierdzisz plan, sprawdź go według tej tabeli. Każdy wiersz kosztuje teraz niewiele, a po uruchomieniu migracji dużo.

SprawdzenieJak wygląda zła odpowiedź
Zgodność z konwencjamiid serial w schemacie, który wszędzie indziej używa UUID jako tekstu
Zachowanie przy usuwaniuON DELETE CASCADE z users do teams, które usuwa zespół, gdy odchodzi jego właściciel
Niezmienniki w bazie„dokładnie jeden właściciel” pilnowany tylko w kodzie aplikacji, bez częściowego indeksu unikalnego
Indeksy wynikają z zapytańindeks na każdym kluczu obcym i żadnego na najczęstszym wyszukiwaniu (team_id, role)

Wygeneruj plik migracji i sprawdź go na jednorazowej bazie

Dział zatytułowany „Wygeneruj plik migracji i sprawdź go na jednorazowej bazie”

Claude Code pisze migrację. Nie stosuje jej nigdzie poza bazą roboczą. Wzorce bez przestojów, takie jak expand-contract, backfill w partiach i budowa indeksów online, szczegółowo opisuje strona migracje baz danych i kodu. Ta sekcja dotyczy pętli, którą przechodzisz przy każdej migracji.

  1. Utwórz plik, nie stosując go. Użyj polecenia create-only swojego narzędzia: npx prisma migrate dev --create-only --name add_teams dla Prismy albo npx drizzle-kit generate dla Drizzle. Potem poproś Claude Code o przejrzenie i uzupełnienie wygenerowanego SQL.

  2. Przepuść ją przez linter. Squawk wykrywa blokujące instrukcje w migracjach Postgresa. Uruchom npx -y squawk-cli prisma/migrations/*/migration.sql (squawk-cli 2.66.0 według npm z 2026-09-26) i wklej każde znalezisko z powrotem do Claude Code.

  3. Wykonaj up, down, up na bazie roboczej i porównaj schematy. To dowód, że działa zarówno migracja, jak i jej wycofanie. Zwykły psql nie zapisuje nic w tabeli historii migracji narzędzia, więc ta tabela nie zaburza porównania. Pętla zakłada, że baza robocza ma już zastosowane wszystkie migracje sprzed add_teams, czyli stan, w jakim zostawia ją uruchomienie Prismy z --create-only. Ani create-only w Prismie, ani drizzle-kit generate (drizzle-kit 0.31.11 nie ma migracji down) nie tworzy down.sql; pisze go Claude Code na podstawie promptu z kroku 1. W Drizzle wygenerowany plik leży w drizzle/<numer>_<nazwa>.sql, a nie w osobnym katalogu, więc ustaw M i obie ścieżki plików na niego i na napisany ręcznie plik down.

    Okno terminala
    # Terminal albo sesja Claude Code: dotyka tylko bazy roboczej
    M=$(ls -d prisma/migrations/*_add_teams)
    pg_dump --schema-only "$DATABASE_URL" > /tmp/schema-before.sql
    psql -v ON_ERROR_STOP=1 "$DATABASE_URL" -f "$M/migration.sql"
    psql -v ON_ERROR_STOP=1 "$DATABASE_URL" -f "$M/down.sql"
    pg_dump --schema-only "$DATABASE_URL" > /tmp/schema-after-down.sql
    diff /tmp/schema-before.sql /tmp/schema-after-down.sql && echo "down path restores the schema"
    psql -v ON_ERROR_STOP=1 "$DATABASE_URL" -f "$M/migration.sql"

    Claude Code może przejść tę pętlę sam, bo jedyna baza w jego powłoce to baza robocza. Pusty diff i czyste drugie zastosowanie migracji to dowód, którego potrzebujesz. Nie musisz czytać SQL linijka po linijce, żeby mu zaufać.

  4. Otwórz pull request z dowodami. Wynik lintera, diff schematu i przebieg testów trafiają do opisu. CI powtarza test up-down-up na świeżej bazie, a właściciel schematu zatwierdza zmianę. Po merge’u migrację stosuje pipeline. Zobacz wdrożenie.

Claude Code częściej pisze poprawny SQL, gdy widzi plan zapytania, zamiast go zgadywać. Daj mu zapytanie, wynik EXPLAIN i dostęp do schematu, a potem poproś o mierzalny wynik.

Kod ORM ukrywa SQL, a w ukrytym SQL mieszkają pętle N+1 i nieograniczone include. Poproś zarówno o kod ORM, jak i o SQL, który on generuje, a kryterium akceptacji niech będzie test.

Skrypty seedujące psują się na dwa przewidywalne sposoby: wstawiają wiersze w złej kolejności zależności i tworzą duplikaty przy drugim uruchomieniu. Zapisz oba ograniczenia w prompcie.

Do testów poproś o fabryki zgodne z tests/fixtures/ (createTestUser(overrides?), createTestTeam(owner, overrides?)) i o owinięcie każdego testu transakcją, która się wycofuje. Fabryki trzymają dane testu obok jego asercji, więc test da się zrozumieć bez zaglądania do pliku seedów. Strategię testowania w ogóle opisuje strona o testowaniu.

Zmapuj użycie bazy subagentami przed ryzykowną zmianą

Dział zatytułowany „Zmapuj użycie bazy subagentami przed ryzykowną zmianą”

Zanim zmienisz nazwę kolumny albo podzielisz tabelę, znajdź każde miejsce, które od niej zależy. Subagenty przeszukują kod równolegle i zwracają podsumowania, więc główna sesja zachowuje kontekst na samą zmianę.

Jeśli chcesz mieć specjalistę od bazy na stałe, zdefiniuj go raz w .claude/agents/. Opisuje to strona własne subagenty.

Audyt uruchamiany z harmonogramu albo dla każdego pull requesta nie potrzebuje człowieka przy klawiaturze. claude -p wykonuje jeden prompt i kończy działanie. Ogranicz go do narzędzi tylko do odczytu flagą --tools i poproś o ustrukturyzowany wynik przez --json-schema, żeby skrypt odczytał znaleziska z pola structured_output.

Okno terminala
# CI albo terminal: audyt schematu tylko do odczytu, wynik czytelny dla maszyny
claude -p "Read prisma/schema.prisma and prisma/migrations/. Report: tables without a primary key, \
foreign keys without a supporting index, nullable columns that every write path sets, \
and naming that breaks the conventions in CLAUDE.md. One finding per issue." \
--tools "Read,Grep,Glob" \
--output-format json \
--json-schema '{"type":"object","properties":{"findings":{"type":"array","items":{"type":"object","properties":{"table":{"type":"string"},"column":{"type":"string"},"issue":{"type":"string"},"fix":{"type":"string"}},"required":["table","issue","fix"]}}},"required":["findings"]}' \
| jq '.structured_output.findings'

--tools określa, które wbudowane narzędzia w ogóle istnieją w przebiegu, więc audyt nie ma do dyspozycji Bash, Edit ani Write. To mocniejsze ograniczenie niż --allowedTools, które tylko zatwierdza narzędzia z góry: claude -p startuje w trybie Manual (od v2.1.285 w trybie auto u zewnętrznych dostawców lub z wyłączoną telemetrią) i choć wszystko, co wymagałoby zgody, zostaje odrzucone (nikt nie odpowie na pytanie), tryb Manual nadal bez pytania wykonuje odczyty plików i wbudowane polecenia powłoki tylko do odczytu. W CI dodaj --max-budget-usd, żeby ograniczyć koszt, i nigdy nie uruchamiaj tego joba na niezaufanym kodzie z pull requesta, gdy w środowisku jest sekret. Bezpieczny wzorzec CI opisuje strona CI/CD z Claude Code.

Sprawdzasz dowody, które zostawia każdy krok, a nie podsumowanie agenta i nie każdą linię SQL.

WynikBramka, która go dowodziKto zatwierdza
Projekt schematuPlan wymienia zapytania, które obsługuje, i ograniczenie za każdym niezmiennikiemTy, zanim zatwierdzisz tryb planowania
Plik migracjiSquawk przechodzi; up, down, up na świeżej bazie z pustym diffem schematu; CI to powtarzaWłaściciel schematu, przez CODEOWNERS na katalogu migracji
Zapytanie albo indeksEXPLAIN (ANALYZE) przed i po na tych samych danych; po wdrożeniu średni czas tego zapytania w pg_stat_statementsAutor, z planami w pull requeście
Funkcja ORMTest, który sprawdza dokładne wiersze, łącznie z przypadkami granicznymiCI
Skrypt seedującyDwa uruchomienia, identyczne liczby wierszyCI

Recenzent czyta opis pull requesta, plany i diff schematu, a uwagę poświęca liniom, których bramki nie ocenią: zachowaniu przy usuwaniu, nieodwracalnym krokom i danym, które opuszczają bazę. Samą recenzję opisuje strona jak recenzować pull request agenta.

Co psuje się przy pracy z bazą w Claude Code i jak z tego wyjść

Dział zatytułowany „Co psuje się przy pracy z bazą w Claude Code i jak z tego wyjść”

Migracja blokuje dużą tabelę. Instrukcja była poprawna, ale wzięła blokadę ACCESS EXCLUSIVE, na przykład ALTER TABLE … ADD COLUMN … NOT NULL DEFAULT z niestałą wartością domyślną albo indeks budowany bez CONCURRENTLY. Wyjście: anuluj migrację, jeśli nadal czeka (SELECT pg_cancel_backend(pid) dla zablokowanej instrukcji), a potem uruchom ponownie prompt migracji z liczbą wierszy w nagłówku pliku i zastosuj wzorce bez przestojów.

CREATE INDEX CONCURRENTLY cannot run inside a transaction block. Twoje narzędzie migracji owija każdy plik transakcją. Przenieś indeks do osobnej migracji i użyj udokumentowanego w tym narzędziu sposobu uruchomienia pliku poza transakcją.

Migracja SQLite albo Cloudflare D1 pada na ALTER TABLE. SQLite obsługuje ADD COLUMN, RENAME COLUMN (od 3.25.0) i DROP COLUMN (od 3.35.0, z ograniczeniami), ale nie zmianę typu kolumny ani dodanie ograniczenia do istniejącej kolumny, i nie ma ADD COLUMN IF NOT EXISTS. Poproś Claude Code o sekwencję przebudowy tabeli (nowa tabela, kopia, usunięcie, zmiana nazwy). W zwykłym SQLite wykonaj ją w jednej transakcji, z PRAGMA foreign_keys = OFF ustawionym przed jej rozpoczęciem. W D1 nie dodawaj BEGIN/COMMIT: D1 sam wykonuje plik migracji w transakcji (Wrangler 4.135.0 usuwa pojedynczą parę BEGIN TRANSACTION;/COMMIT; i odrzuca plik z więcej niż jedną), więc zamiast tego użyj w pliku PRAGMA defer_foreign_keys = on. W obu przypadkach przetestuj przebudowę na kopii prawdziwych danych, bo to przy kopiowaniu giną wiersze.

Claude Code uruchomił migrację na złej bazie. Sesja odziedziczyła DATABASE_URL, które wskazywało staging. Wyjście: zastosuj tam migrację down albo odtwórz bazę z kopii zapasowej zrobionej przed zmianą. Zapobieganie: uruchamiaj sesje z powłoki z bazą roboczą i przed pracą z bazą sprawdź w sesji echo $DATABASE_URL.

Skrypt seedujący łamie klucz obcy albo duplikuje wiersze przy drugim uruchomieniu. Wstawiał w złej kolejności albo używał zwykłych insertów. Uruchom ponownie prompt seedujący, który wymaga kolejności kluczy obcych i upsertów po kluczach naturalnych, i zostaw test „uruchom dwa razy, porównaj liczby”.

Migracja down istnieje, ale nie przywraca danych. Usunięcie kolumny w ścieżce up i ponowne dodanie jej w ścieżce down daje pustą kolumnę. Traktuj każdy destrukcyjny krok up jako nieodwracalny: zrób kopię zapasową albo zostaw starą kolumnę do fazy contract i napisz to na początku down.sql.

Claude Code po migracji wciąż używa starej nazwy kolumny. Pracuje na swoim wcześniejszym rozumowaniu, a nie na aktualnym schemacie. Poproś go o ponowne przeczytanie pliku schematu albo uruchom /clear i zacznij kolejne zadanie w świeżym kontekście.

Ten sam proces w innych narzędziach: praca z bazą danych w Codex i projektowanie bazy w Cursorze. Widok wspólny dla wszystkich narzędzi znajdziesz na stronie projektowanie baz danych i zapytań.