Przejdź do treści
Biblioteka skilli
Dane i analityka · Budowanie i kod

postgres-schema

/postgres-schema

Projektuje lub sprawdza tabele PostgreSQL: typy kolumn, ograniczenia chroniące dane i indeksy, których potrzebują zapytania.

Repozytorium
yaap ↗
Licencja
MIT
Ostatnia zmiana repozytorium
13.11.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
1
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 13.11.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Projektuje lub sprawdza tabele PostgreSQL: typy kolumn, ograniczenia chroniące dane i indeksy, których potrzebują zapytania.

Oryginalny opis (EN)

Design or review PostgreSQL tables with the right column types, constraints that keep bad data out and the indexes the queries need. Use it whenever you create or change a table, choose a type, add a foreign key or index, model money, time, status or JSON, or review an ORM model.

Jak działa

  1. 1. Model first
  2. 2. Types
  3. 3. Constraints
  4. 4. Indexes
  5. 5. Example
  6. 6. Things that surprise people
  7. 7. Keep the schema in migrations
  8. Report
Sekcje z nagłówków SKILL.md, w oryginale · 98 linii, 864 słów
Podgląd SKILL.md
---
name: postgres-schema
description: Design or review PostgreSQL tables with the right column types, constraints that keep bad data out and
  the indexes the queries need. Use it whenever you create or change a table, choose a type, add a foreign key or
  index, model money, time, status or JSON, or review an ORM model.
license: MIT
metadata:
  sources: wshobson/plugins/database-design/skills/postgresql-table-design
---

# PostgreSQL schema

The schema is the last line of defence for your data. Application checks have bugs and get bypassed by scripts and
other services; a constraint holds for every writer. Make the database refuse what must never be stored.

## 1. Model first

Normalise to third normal form: each fact in one place. Denormalise only for a read you measured as too slow, and
write down which copy is the source. Names are `snake_case`, unquoted, tables plural (`orders`), foreign keys
`<thing>_id`.

## 2. Types

| Data | Use | Avoid |
|---|---|---|
| Ids | `bigint GENERATED ALWAYS AS IDENTITY`; `uuid` when ids are made outside the database or must not be guessable | `serial`, `integer` that runs out |
| Text | `text`, with a `CHECK (length(col) <= n)` when there is a real limit | `varchar(255)` out of habit, `char(n)` |
| Money and exact numbers | `numeric(12, 2)`, or `bigint` in minor units | `real`, `double precision`, the `money` type |
| Moments in time | `timestamptz` | `timestamp` without a time zone |
| Dates | `date` | text |
| Yes or no | `boolean NOT NULL` | a nullable boolean, unless "unknown" is a real third value |
| Status with a few stable values | `text` with a `CHECK (status IN (…))`, or a lookup table | a free string with no check |
| Optional, varying attributes | `jsonb`, for the parts you do not filter on often | `json`, or `jsonb` for core fields |

A native `enum` type is fine for a small set that never changes; removing a value from one is hard.

## 3. Constraints

- **`NOT NULL` by default.** Make a column nullable only when "no value" is a real state, and know what it means.
- **Primary key on every table.**
- **Foreign keys for every reference,** with a deliberate `ON DELETE`: `RESTRICT` (the default choice), `CASCADE` for
  rows that cannot exist without their parent, `SET NULL` when the link is optional.
- **`UNIQUE` for natural keys** (an email, an order number). A unique column allows many `NULL`s; use
  `UNIQUE NULLS NOT DISTINCT` (PostgreSQL 15 and later) when one `NULL` is the limit.
- **`CHECK` for rules on one row** (`total >= 0`, `ends_at > starts_at`). A `CHECK` lets `NULL` pass, so pair it with
  `NOT NULL` where needed.
- **Exclusion constraints** for "no overlap" rules, such as two bookings of one room at the same time.

## 4. Indexes

An index costs space and slows every write. Add one for a query that needs it, and check with `EXPLAIN ANALYZE` that
it is used.

- **Every foreign key column.** PostgreSQL does not index them for you, and joins and cascading deletes need them.
- **Composite indexes** follow the left-most rule: `(customer_id, created_at)` serves a filter on `customer_id`, or on
  both, but not on `created_at` alone. Put the equality columns first, the range or sort column last.
- **Partial indexes** for a small hot subset: `WHERE status = 'open'`.
- **Expression indexes** for a computed lookup, such as `lower(email)`; the query must use the same expression.
- **GIN** for `jsonb` containment, arrays and full-text search; **BRIN** for very large tables ordered by time.

## 5. Example

```sql
CREATE TABLE orders (
    id          bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    customer_id bigint NOT NULL REFERENCES customers (id) ON DELETE RESTRICT,
    number      text NOT NULL UNIQUE,
    status      text NOT NULL DEFAULT 'open' CHECK (status IN ('open', 'paid', 'cancelled')),
    total       numeric(12, 2) NOT NULL CHECK (total >= 0),
    currency    char(3) NOT NULL CHECK (currency ~ '^[A-Z]{3}$'),
    note        text CHECK (length(note) <= 2000),
    created_at  timestamptz NOT NULL DEFAULT now(),
    updated_at  timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX orders_customer_id_created_at_idx ON orders (customer_id, created_at);
CREATE INDEX orders_open_created_at_idx ON orders (created_at) WHERE status = 'open';
```

`char(3)` is one of the few good uses of a fixed length: a currency code is always three letters.

## 6. Things that surprise people

- Identity and sequence values have gaps after rollbacks; that is normal, do not try to fill them.
- `now()` is the start of the transaction, the same for every row in it; `clock_timestamp()` is the wall clock.
- A value too long for its type fails instead of being cut off; that is a feature.
- Updates leave dead rows that vacuum cleans up; a table where wide rows change constantly needs attention.
- Names over 63 characters are truncated with only a NOTICE, which is easy to miss in a migration log, so two long
  names can end up the same; keep index and constraint names short and explicit.

## 7. Keep the schema in migrations

Every schema change goes through a migration in the repository, and the tests check that the migrated schema matches
the models. Changing a table that already holds data is a job for the `safe-migrations` skill.

## Report

For a new or reviewed table:

```
Table: <name and what one row is>
Keys: <primary key, natural keys, foreign keys with ON DELETE>
Checks: <the rules the database enforces>
Indexes: <each with the query it serves>
Open questions: <nullability or delete behaviour the user must decide>
```

Wersje

W bazie nie ma innych skilli o nazwie postgres-schema.

Migawka bazy z 13.11.2026 · wersja paczki 6605a2449d71 (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100design-postgres-tables
    Wspiera ogólne projektowanie tabel PostgreSQL: typy danych, ograniczenia, indeksy, normalizację, schematy JSONB i tabele intensywnie aktualizowane lub z upsertami.
  • 100flux-schema
    Projektuje i buduje schemat bazy danych: tabele, kolumny, typy, indeksy, ograniczenia i relacje, a z opisu dziedziny generuje schemat i zapisuje pliki.
  • 100postgresql-table-design
    Projektuje lub przegląda schematy specyficzne dla PostgreSQL: dobre praktyki, typy danych, indeksowanie, ograniczenia, wzorce wydajności i bardziej złożone funkcje.
  • 100postgres
    Wykonuje doraźne zapytania SELECT do PostgreSQL, analizuje plany EXPLAIN i ANALYZE, sprawdza schematy, indeksy i blokady oraz bada wolne zapytania, domyślnie tylko do odczytu.
  • 100postgres
    Projektuje i stroi schematy PostgreSQL, zapytania, indeksy, blokady i vacuum, a także pomaga przy migracjach na żywej tabeli.
  • 87postgres-database-migration
    Planuje i testuje migracje schematu PostgreSQL na produkcyjnych danych: dodawanie kolumn, zmianę typów, indeksy i ograniczenia bez przestojów.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.