Klasyczny SQL nie przewiduje przechowywania wielu wartości w jednej komórce - model relacyjny wymaga normalizacji. Jednak w nowoczesnych zadaniach często spotykane są pola typu "lista tagów", "skala ocen", gdzie wygodnie operować właśnie wieloma wartościami na poziomie pojedynczego wiersza. Niektóre systemy baz danych (PostgreSQL, Oracle) oferują typy danych ARRAY lub podobne mechanizmy.
Używanie tablic narusza zasadę normalizacji, utrudnia wiele operacji (filtrowanie, aktualizacja, indeksowanie), a także sprawia, że kod jest mniej przenośny między systemami baz danych. Jednak bywa to wygodne lub nieuniknione - na przykład do cache'owania lub szybkiego wyszukiwania po niewielkich listach wartości.
CREATE TABLE products ( id SERIAL PRIMARY KEY, tags TEXT[] ); -- Wstawianie: INSERT INTO products(tags) VALUES (ARRAY['eco','sale','hot']); -- Wyszukiwanie w tablicy: SELECT * FROM products WHERE 'eco' = ANY (tags);
Kluczowe cechy:
Czy można indeksować poszczególne elementy tablicy?
W PostgreSQL - tak, za pomocą indeksów GIN/GIST:
CREATE INDEX idx_tags ON products USING GIN (tags);
Jak szybciej sprawdzić przynależność wartości do tablicy w kolumnie tekstowej przez separator?
SQL standardowo tego nie obsługuje, używa się wyszukiwania wzorcowego:
SELECT * FROM users WHERE ',admin,' like concat('%,',role,',%');
Ale to podejście jest niepewne i wolne.
Ile wartości można przechowywać w tablicy i co je ogranicza?
Ograniczenie zależy od systemu baz danych - na przykład w PostgreSQL ograniczenie dotyczy jedynie rozmiaru wiersza (1–2 MB).
W projekcie e-commerce tagi produktów postanowiono przechowywać jako ciąg rozdzielony przecinkiem w jednej kolumnie. Bardzo utrudniło to szybkie wyszukiwanie produktów po tagu, błędy w filtrowaniu, zdarzało się powtarzanie tagów z powodu błędów w analizie.
Plusy:
Minusy:
W PostgreSQL dla małych, niezmiennych zbiorów (role użytkowników) użyto ARRAY i indeksu GIN. Dla większych - osobną tabelę ról.
Plusy:
Minusy: