Per collegare prodotti e ordini in Access devi usare una tabella ponte, normalmente chiamata DettagliOrdine, perché tra Ordini e Prodotti esiste una relazione molti-a-molti. Un ordine può contenere molti prodotti e lo stesso prodotto può comparire in molti ordini. La struttura corretta crea due relazioni uno-a-molti: Ordini.IDOrdine → DettagliOrdine.IDOrdine e Prodotti.IDProdotto → DettagliOrdine.IDProdotto.
Indice
- Perché serve una tabella ponte
- Struttura Ordini
- Struttura Prodotti
- Struttura DettagliOrdine
- Relazioni e integrità
- Query e calcoli
- Maschere
- Errori comuni
- FAQ
Perché non basta collegare direttamente Ordini e Prodotti
Se aggiungi IDProdotto direttamente alla tabella Ordini, ogni ordine potrebbe contenere un solo prodotto. Se aggiungi Prodotto1, Prodotto2, Prodotto3, crei gruppi ripetuti e un modello difficile da interrogare. La soluzione relazionale è una riga per ogni prodotto presente in un ordine.
DettagliOrdine rappresenta proprio questa riga. Contiene la chiave dell’ordine, la chiave del prodotto e attributi come quantità, prezzo unitario, sconto e aliquota applicata. Queste informazioni appartengono alla combinazione ordine-prodotto.
Struttura della tabella Ordini
Ordini può contenere IDOrdine Autonumerazione e chiave primaria, IDCliente Numero/Intero lungo, DataOrdine, StatoOrdine, MetodoPagamento, Note e altri campi di intestazione. Il totale può essere calcolato dai dettagli invece di essere memorizzato, salvo specifiche esigenze di congelamento storico o integrazione.
La tabella non deve contenere una colonna per ogni possibile prodotto.
Struttura della tabella Prodotti
Prodotti può contenere IDProdotto Autonumerazione e chiave primaria, CodiceProdotto o SKU, Descrizione, Categoria, PrezzoListino, Attivo e altri attributi. L’ID tecnico rimane stabile anche se il codice commerciale cambia.
Se il codice prodotto deve essere univoco, imposta un indice univoco separato senza usarlo necessariamente come chiave primaria.
Struttura della tabella DettagliOrdine
Una struttura robusta include IDDettaglio Autonumerazione come chiave primaria, IDOrdine Numero/Intero lungo, IDProdotto Numero/Intero lungo, Quantità, PrezzoUnitario, Sconto e eventualmente IVA. In alternativa puoi usare una chiave composta IDOrdine+IDProdotto se la regola vieta lo stesso prodotto ripetuto in più righe dello stesso ordine.
L’IDDettaglio tecnico è spesso più comodo per maschere e modifiche. Puoi comunque creare un indice univoco composto su IDOrdine e IDProdotto se vuoi impedire duplicati.
Tipi di dati corretti
Se Ordini.IDOrdine e Prodotti.IDProdotto sono Autonumerazione, i campi corrispondenti in DettagliOrdine devono normalmente essere Numero con Dimensione campo Intero lungo. Non usare Autonumerazione sulle chiavi esterne: devono ricevere gli ID già esistenti del padre.
Quantità può essere Numero con una dimensione coerente con il processo; PrezzoUnitario dovrebbe usare Valuta quando appropriato per importi monetari.
Creare la relazione Ordini→DettagliOrdine
- Apri Strumenti database > Relazioni.
- Aggiungi Ordini e DettagliOrdine.
- Trascina Ordini.IDOrdine su DettagliOrdine.IDOrdine.
- Attiva Applica integrità referenziale.
- Valuta l’eliminazione a catena solo se eliminare un ordine deve eliminare anche le sue righe.
- Conferma e salva.
Questa è una relazione uno-a-molti: un ordine ha molte righe di dettaglio.
Creare la relazione Prodotti→DettagliOrdine
- Aggiungi Prodotti alla finestra Relazioni.
- Trascina Prodotti.IDProdotto su DettagliOrdine.IDProdotto.
- Attiva integrità referenziale.
- Evita normalmente di eliminare a catena i dettagli quando cancelli un prodotto storico: spesso è meglio rendere il prodotto inattivo.
- Salva.
Ora lo stesso prodotto può comparire in molti dettagli appartenenti a ordini diversi.
Perché l’integrità referenziale è importante
Con il vincolo attivo non puoi inserire una riga DettagliOrdine con IDOrdine inesistente o IDProdotto inesistente. Questo impedisce righe orfane e rende affidabili query e report. Inoltre Access blocca cancellazioni del padre che romperebbero lo storico, a meno che tu non abbia scelto una cascata.
Le regole a catena vanno configurate separatamente per le due relazioni.
Eliminazione a catena sull’ordine
Può essere ragionevole che eliminando un ordine di prova vengano eliminate anche le sue righe DettagliOrdine. In un gestionale reale, però, valuta se gli ordini vengono davvero cancellati o se è preferibile usare uno StatoOrdine. Le transazioni storiche spesso devono essere conservate.
Se attivi la cascata, testa su una copia perché una query DELETE sull’ordine può eliminare molte righe figlie.
Eliminazione a catena sul prodotto
Di solito è più rischiosa. Un prodotto fuori catalogo può essere presente in ordini storici. Se elimini il prodotto e cancelli a catena i dettagli, distruggi lo storico delle vendite. Meglio impostare Prodotti.Attivo=False e impedire la selezione nei nuovi ordini mantenendo il record per quelli vecchi.
La conservazione storica è una regola di business, non soltanto una scelta tecnica.
Query per mostrare un ordine con i prodotti
SELECT Ordini.IDOrdine, Prodotti.CodiceProdotto, Prodotti.Descrizione, DettagliOrdine.Quantità, DettagliOrdine.PrezzoUnitario FROM (Ordini INNER JOIN DettagliOrdine ON Ordini.IDOrdine = DettagliOrdine.IDOrdine) INNER JOIN Prodotti ON DettagliOrdine.IDProdotto = Prodotti.IDProdotto;
Questa query produce una riga per dettaglio e può alimentare report, fatture o esportazioni.
Calcolare l’importo della riga
In una query puoi aggiungere un campo calcolato:
ImportoRiga: [Quantità]*[PrezzoUnitario]
Se gestisci sconti, la formula può includerli. Evita di memorizzare valori calcolabili senza motivo, ma valuta lo storico: PrezzoUnitario dell’ordine deve spesso essere salvato perché il listino prodotto può cambiare.
Perché salvare il prezzo nel dettaglio
Prodotti.PrezzoListino rappresenta il prezzo corrente; DettagliOrdine.PrezzoUnitario rappresenta il prezzo applicato al momento dell’ordine. Se recuperassi sempre il prezzo corrente, un aggiornamento del listino cambierebbe retroattivamente i vecchi ordini.
Questa è una delle eccezioni apparenti alla normalizzazione: non è duplicazione casuale, ma conservazione di un fatto storico della transazione.
Maschera Ordine e sottomaschera Dettagli
Crea una maschera principale basata su Ordini e una sottomaschera continua basata su DettagliOrdine. Collega master/figlio tramite IDOrdine. Nella sottomaschera usa una combo box per IDProdotto che mostra CodiceProdotto e Descrizione ma salva l’ID.
Quando l’utente seleziona un prodotto, puoi copiare il prezzo corrente nel campo PrezzoUnitario con una macro o VBA, preservando poi il valore storico.
Combo box prodotti
La Row Source della combo può filtrare Prodotti.Attivo=True e ordinare per descrizione. La Bound Column deve essere IDProdotto. Nascondi la colonna ID se vuoi un’interfaccia più leggibile.
Non salvare la descrizione del prodotto come collegamento; usa sempre la chiave.
Impedire lo stesso prodotto due volte
Se vuoi una sola riga per prodotto in ogni ordine, crea un indice composto univoco su IDOrdine+IDProdotto. In alternativa consenti righe multiple se il processo prevede lotti, prezzi o configurazioni diverse.
La scelta dipende dal significato dei dati. Non imporre unicità se esistono casi reali in cui la stessa referenza deve comparire più volte.
Verificare record orfani
Per controllare dettagli senza prodotto:
SELECT DettagliOrdine.IDDettaglio, DettagliOrdine.IDProdotto FROM DettagliOrdine LEFT JOIN Prodotti ON DettagliOrdine.IDProdotto = Prodotti.IDProdotto WHERE Prodotti.IDProdotto IS NULL;
Ripeti una query simile per IDOrdine. Correggi gli orfani prima di attivare l’integrità.
Normalizzazione
La tabella ponte è una conseguenza della normalizzazione. Evita gruppi ripetuti e consente un numero illimitato di prodotti per ordine. Aggiungere un nuovo prodotto non richiede modificare la struttura di Ordini.
Query e report diventano più semplici perché ogni riga ha una granularità chiara: un prodotto in un ordine.
Relazioni e join
Le relazioni salvate definiscono il modello; i join nelle query decidono come leggere i dati. Access può proporre automaticamente i join grazie alle relazioni. Se una query mostra molte righe, ricorda che la granularità di DettagliOrdine è più fine di quella di Ordini.
Non usare DISTINCT per nascondere righe legittime dei dettagli.
Indici e prestazioni
IDOrdine e IDProdotto nella tabella ponte sono usati frequentemente nei join e possono beneficiare di indici. Se usi una chiave composta, l’indice univoco serve anche a garantire la regola. Non indicizzare indiscriminatamente ogni campo perché gli indici aumentano il costo degli aggiornamenti.
Su archivi molto grandi valuta un back-end SQL Server mantenendo Access come front-end.
Database multiutente
In una soluzione condivisa conserva le tabelle nel back-end e distribuisci un front-end locale a ogni utente. Definisci le relazioni nel back-end che ospita i dati. Esegui modifiche strutturali quando nessuno sta lavorando.
Se il back-end è server, foreign key e vincoli devono essere definiti nel server.
Access Microsoft 365 e Access 2024
La procedura è per Access desktop su Windows, inclusi Access per Microsoft 365 e Access 2024. La scelta 32 o 64 bit non cambia il modello relazionale. Access Runtime è pensato per eseguire applicazioni già distribuite.
Non esiste un’app Access desktop nativa per macOS.
Errori comuni
Mettere Prodotto1/Prodotto2 in Ordini; collegare direttamente Ordini e Prodotti senza ponte; usare chiavi esterne Autonumerazione; cancellare prodotti storici a catena; recuperare sempre il prezzo corrente invece di conservare il prezzo dell’ordine; salvare descrizioni al posto degli ID.
Questi errori limitano la scalabilità e rendono le query difficili.
Troubleshooting
Se Access non crea la relazione, controlla tipi, chiavi e record orfani. Se la combo mostra il prodotto ma salva un valore sbagliato, verifica Bound Column. Se compaiono duplicati, controlla se sono righe di dettaglio legittime o se manca un indice composto.
Se il totale è sbagliato, verifica quantità, prezzo e gestione dei Null con Nz quando appropriato.
Test pratico
Crea un ordine di prova e aggiungi tre prodotti. Verifica che ogni riga abbia lo stesso IDOrdine e IDProdotto diversi. Prova lo stesso prodotto in un altro ordine. Poi esegui la query e il report. Prova un IDProdotto inesistente: l’integrità deve bloccarlo.
Testa le cancellazioni su una copia prima di abilitare cascata.
FAQ
Perché serve DettagliOrdine?
Per risolvere il molti-a-molti tra Ordini e Prodotti.
Posso usare IDOrdine+IDProdotto come chiave primaria?
Sì se quella combinazione deve essere univoca; un IDDettaglio tecnico è spesso più flessibile.
Dove salvo Quantità?
In DettagliOrdine.
Dove salvo il prezzo applicato?
In DettagliOrdine, per conservare lo storico.
Devo cancellare un prodotto fuori catalogo?
Di solito no: rendilo inattivo per preservare ordini storici.
Link utili
Consulta la categoria Guide Access, tabella ponte, relazioni molti-a-molti, creare relazioni e tabella Prodotti.
Fonte ufficiale: Microsoft Support: guida alle relazioni tra tabelle.
Conclusione
Per collegare prodotti e ordini in Access crea DettagliOrdine e due relazioni uno-a-molti. Usa chiavi tecniche stabili, integrità referenziale, prezzo storico nel dettaglio e una maschera ordine con sottomaschera. È il modello standard che rende il database flessibile, interrogabile e coerente.