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:

  1. Carica tutto in un database di staging, con vincoli rilassati.
  2. Misura i dati: duplicati, orfani, valori nulli, formati.
  3. 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

AccessPostgreSQLAttenzione
Contatore (AutoNumber)integer generated by default as identityriallinea la sequenza dopo il carico
Testo brevetext o varchar(n)spazi finali e stringhe vuote al posto di NULL
Memo / Testo lungotexta volte contiene RTF o HTML
Sì/NobooleanAccess salva il vero come -1
Valutanumeric(19,4)mai float per gli importi
Data/oratimestamp o datedate "zero" come 30/12/1899 usate al posto di NULL
Allegato, OLEbytea o file su discomeglio 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.

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

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.

Invia un messaggio → Prenota una call gratuita ↗