ProgrammazioneSviluppatore Fullstack

Come lavorare con array e analoghi degli array in SQL per memorizzare e analizzare valori multipli in una singola cella, e quando è giustificato tale approccio?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Storia della domanda

Il SQL classico non prevede la memorizzazione di più valori in una singola cella — il modello relazionale richiede normalizzazione. Tuttavia, nelle sfide moderne si incontrano spesso campi di tipo "lista di tag", "scala di valutazione", dove è conveniente operare proprio con un insieme di valori a livello di singola riga. Alcuni DBMS (PostgreSQL, Oracle) forniscono tipi di dati ARRAY o meccanismi analoghi.

Problema

L'uso degli array viola il principio di normalizzazione, complica molte operazioni (filtraggio, aggiornamento, indicizzazione) e rende il codice meno portabile tra DBMS. Ma a volte è comodo o inevitabile — ad esempio, per caching o ricerca rapida in piccole liste di valori.

Soluzione

  • In PostgreSQL il supporto per gli array è nativo. Esempio:
CREATE TABLE products ( id SERIAL PRIMARY KEY, tags TEXT[] ); -- Inserimento: INSERT INTO products(tags) VALUES (ARRAY['eco','sale','hot']); -- Ricerca nell'array: SELECT * FROM products WHERE 'eco' = ANY (tags);
  • In MySQL 5.x gli array non esistono, si usano spesso JSON o stringhe separate e funzioni per l'analisi.
  • In Oracle — collezioni, nested table/varray.
  • Per compiti analitici ottimali è meglio normalizzare (creare una tabella secondaria con product_tags) e utilizzare JOIN, mentre l'array va conservato solo in casi speciali (performance o requisiti specifici).

Caratteristiche chiave:

  • Comodo quando l'array è realmente necessario e DBMS lo supporta.
  • Problemi con indici e filtraggio con grandi array.
  • Non portabile tra DBMS, complica il supporto.

Domande trabocchetto.

Si può indicizzare singoli elementi dell'array?

In PostgreSQL — sì, tramite indici GIN/GIST:

CREATE INDEX idx_tags ON products USING GIN (tags);

Come controllare più velocemente se un valore è presente in un array in una colonna di stringhe attraverso un delimitatore?

SQL standard non è in grado, si utilizza la ricerca per pattern:

SELECT * FROM users WHERE ',admin,' like concat('%,',role,',%');

Ma questo approccio non è affidabile e lento.

Quanti valori si possono memorizzare in un array, e cosa lo limita?

Il limite dipende dal DBMS — ad esempio, in PostgreSQL c'è un limite solo sulla dimensione della riga (1–2 MB).

Errori tipici e anti-pattern

  • Memorizzare array in una singola cella per "semplicità" e complicare l'analisi
  • Filtrare valori in modo errato tramite LIKE senza considerare i delimitatori
  • Fare affidamento sull'unicità e sull'indicizzazione delle righe-array

Esempio dalla vita reale

Caso negativo

In un progetto e-commerce, i tag dei prodotti sono stati memorizzati come stringa separata da virgole in una singola colonna. È diventato molto difficile cercare rapidamente i prodotti per tag, ci sono stati errori nel filtraggio e la ripetizione dei tag è avvenuta a causa di errori di parsing.

Vantaggi:

  • "Semplice" e rapidamente realizzabile

Svantaggi:

  • Molto lento su larga scala, difficile da mantenere, impossibile garantire l'unicità dei valori

Caso positivo

In PostgreSQL per insiemi piccoli e immutabili (ruoli utente) sono stati usati ARRAY e indice GIN. Per quelli grandi — una tabella separata dei ruoli.

Vantaggi:

  • Ricerca rapida nell'ARRAY tramite indice
  • Resta la compatibilità con il modello relazionale dove necessario

Svantaggi:

  • Non portabile, richiede conoscenza delle caratteristiche avanzate del DBMS