In tante aziende c'è un gestionale nato vent'anni fa su Microsoft Access: sviluppato da un consulente, cresciuto una maschera alla volta, oggi indispensabile. E fragile: file condivisi in rete che si corrompono, limite di 2 GB per file, accesso remoto impossibile, nessuno che sa più come funziona dentro.
Portare i dati su PostgreSQL è spesso il primo passo per rifarlo come applicazione web. In questo articolo racconto il metodo che uso. Le trappole descritte le ho incontrate tutte su dati reali, in un database con decine di tabelle e milioni di righe.
Il principio: lo schema dice cosa volevano, i dati dicono cosa c'è
L'errore più comune è generare lo schema PostgreSQL a partire da quello di Access, lanciare il caricamento e scoprire i problemi uno alla volta, tabella per tabella, a carico fallito. Il metodo che funziona si divide in tre fasi:
- Carica tutto in un database di staging, con vincoli rilassati.
- Misura i dati: duplicati, orfani, valori nulli, formati.
- Decidi, dati alla mano, quali vincoli imporre e cosa bonificare.
1. Estrarre i dati
Su Linux, mdbtools legge i file .mdb e .accdb senza bisogno di Windows:
mdb-tables -1 gestionale.mdb # elenco tabelle
mdb-schema gestionale.mdb postgres > schema.sql # DDL di partenza
mdb-export -D '%Y-%m-%d %H:%M:%S' gestionale.mdb Clienti > Clienti.csv
Per database grandi o con tipi particolari, l'estrazione tramite ODBC da una macchina Windows con il driver Access è più affidabile. Come prima cosa, però, fai una copia del file a gestionale chiuso e lavora su quella.
Controlla anche le tabelle collegate: spesso il file che apre l'utente contiene solo maschere e query, e i dati stanno in uno o più file separati.
2. Tipi di dato: la mappatura
| Access | PostgreSQL | Attenzione |
|---|---|---|
| Contatore (AutoNumber) | integer generated by default as identity | riallinea la sequenza dopo il carico |
| Testo breve | text o varchar(n) | spazi finali e stringhe vuote al posto di NULL |
| Memo / Testo lungo | text | a volte contiene RTF o HTML |
| Sì/No | boolean | Access salva il vero come -1 |
| Valuta | numeric(19,4) | mai float per gli importi |
| Data/ora | timestamp o date | date "zero" come 30/12/1899 usate al posto di NULL |
| Allegato, OLE | bytea o file su disco | meglio estrarli come file |
3. Le trappole sui dati
I campi "Richiesto" non valgono per il passato
In Access un campo può essere marcato come obbligatorio, e lo schema generato lo traduce in NOT NULL. Ma Access applica il vincolo solo ai nuovi inserimenti: le righe create prima che qualcuno attivasse il flag restano nel file con il campo vuoto. Il risultato è un caricamento che si ferma su una riga fantasma di dieci anni fa.
La soluzione: in staging togli i NOT NULL (tranne sulle chiavi primarie), conservando l'elenco originale in una tabella di controllo. Dopo il carico misuri, colonna per colonna, quante righe violerebbero il vincolo, e decidi se bonificarle o abbandonare il vincolo.
La chiave "naturale" che non è unica
Molti gestionali usano codici leggibili come chiave: il codice cliente formato dalle prime lettere della ragione sociale, per esempio. Sembra una chiave primaria, ma due aziende che iniziano con le stesse dieci lettere hanno lo stesso codice. Collidono per costruzione.
select count(*) - count(distinct cod_cliente) as duplicati from clienti;
Se il risultato non è zero, il codice diventa un campo di ricerca non univoco e la chiave primaria diventa l'identificativo numerico. Poi verifica quante righe collegate (ordini, documenti) puntano a un codice ambiguo: da quel numero dipende quanto lavoro di bonifica serve.
Orfani: non sempre sono corruzione
Access permette relazioni senza integrità referenziale, quindi è normale trovare righe figlie che puntano a padri inesistenti. Prima di parlare di database corrotto, guarda il più piccolo ID presente nella tabella padre: se gli orfani puntano tutti a ID più bassi, qualcuno anni fa ha cancellato lo storico vecchio lasciando i dettagli. È potatura, non corruzione, e si decide con il cliente se archiviarli o eliminarli.
Prima di dichiarare una foreign key, provala dentro una transazione annullata:
begin;
alter table righe_ordine add foreign key (id_ordine) references ordini (id);
rollback;
Maiuscole e minuscole
Access confronta il testo ignorando le maiuscole: ROSSI e Rossi sono uguali. PostgreSQL no. Le query del gestionale riscritte senza pensarci restituiscono meno righe, senza nessun errore.
- Per le colonne codice, su PostgreSQL recenti la soluzione più pulita è una collation ICU non deterministica, che ignora le maiuscole ma non gli accenti e vale anche per vincoli di unicità e foreign key:
create collation it_ci (provider = icu, locale = 'it-IT-u-ks-level2', deterministic = false); alter table clienti alter column cod_cliente type text collate it_ci; - Diffida di
citext: confrontato con un'espressione di tipotext(per esempiolower(:parametro)) torna sensibile alle maiuscole e restituisce zero righe senza errori. - Per la ricerca libera su ragioni sociali e descrizioni:
textnormale,ILIKEe un indice trigram (pg_trgm).
4. Prestazioni: gli indici prima di tutto
Un gestionale con una decina di utenti su PostgreSQL non ha bisogno di cache esterne o architetture complicate. Quello che serve sono gli indici giusti: Access ne crea alcuni in automatico, e lo schema migrato spesso li perde. In un caso reale, una ricerca clienti è passata da 733 millisecondi a 1,4 millisecondi con un solo indice. Misura con EXPLAIN ANALYZE le query più usate, prima di pensare all'hardware.
5. La verifica finale
- Conteggio righe tabella per tabella tra Access e PostgreSQL.
- Somme di controllo sui campi importanti: totale fatturato per anno, numero documenti per mese.
- Campioni confrontati a mano con il gestionale originale insieme a chi lo usa ogni giorno.
- Un registro delle decisioni: quali righe sono state bonificate, quali vincoli sono stati tolti e perché.
La logica non sta solo nelle tabelle. Maschere, query salvate e codice VBA contengono regole di business che nessuno ha mai scritto altrove: sconti, arrotondamenti, numerazioni. Migrare i dati è metà del lavoro; l'altra metà è ritrovare quelle regole prima di spegnere il vecchio gestionale.
Posso aiutarti con la tua infrastruttura?
Che tu abbia un progetto da zero o un problema da risolvere, scrivimi o prenota una call gratuita di 30 minuti.