Controllare se esiste una tabella in un Database Access

Il compito sembra facile, ma tra la teoria e la pratica purtroppo c’e’ un abisso.

La prima soluzione consiste nell’interrogare una tabella di sistema presente in tutti i database Access, la MSysObjects.

SELECT * from MSysObjects where Type=1  and Name=’NomeTabella’

Dove NomeTabella e’ il nome della tabella da controllare. Se poi si vuole controllare se con lo stesso nome ci sia una vista, tabella collegata o altra fonte utiie per attingere dati, allora occorre allargare un po’ il Type richiesto:

SELECT MSysObjects.* FROM MSysObjects WHERE (Type=1 OR Type=4 OR Type=5 OR Type=6) and Name=’NomeTabella’

Purtroppo il codice funziona molto bene da Access, ma quando si va ad eseguire da un’applicazione .NET viene restituito un errore di permessi di accesso:
ERROR
[42000] [Microsoft][Driver ODBC Microsoft Access] Impossibile leggere
record. Autorizzazione di lettura non disponibile per "MSysObjects".
ERROR
[42000] 
[Microsoft][ODBC Microsoft Access Driver] Record(s) cannot be read; no read permission on ‘MSysObjects’. 

Ora, molte soluzioni dicono di cambiare i permessi alla tabella MSysObjects, purtroppo pero’ si dimenticano di dire che occorre prima abilitare la visualizzazione degli oggetti di sistema, (Tools – Options – View – System objects), e poi sara’ possibile aggiungere il permesso di Read Data alla tabella MSysObject tramite User and Group Permission, sempre nel menu’ Tools.

Un’ulteriore soluzione, di piu’ alto livello di astrazione, consiste nell’usare la funzione GetOleDbSchemaTable, come spiegato in How To Retrieve Schema Information by Using GetOleDbSchemaTable and Visual Basic .NET.

Per quanto riguarda le Restrictions, il link all’articolo dell’MSDN dove vengono spiegate e’ errato, ma leggendo quanto contenuto in OleDbSchemaGuid Members si possono ricavare comunque tutte: basta aprire la pagina relativa ad ogni Fields ed in fondo vengono presentati i valori corretti delle Restictions che si possono applicare.

A mio avvisto, comunque, il primo metodo, quello del SELECT, rimane comunque il piu’ utile  in quanto si possono controllare con un colpo solo tabelle, viste, tabelle collegate ed altri oggetti (basta modificare il Type). Certo, occorre prima cambiare i permessi del DB che si vuole interrogare. A livello di performance, dalle prove fatte, sembrano essere sostanzialmente le stesse.

Ed infine il codice che ho usato:

Private Function tableExists( _
        ByVal objConn As OleDbConnection, _
        ByVal strTableName As String _
    ) As Boolean
        Dim objCommand As OleDbCommand
        Dim objDR As OleDbDataReader
        Dim strQuery As String
        Dim booTableExists As Boolean

        strQuery = "SELECT * FROM MSysObjects WHERE Type IN (1, 4, 5, 6) AND Name=’" &
        ‘controlla se esiste la tabella
        booTableExists = False
        objCommand = New OleDbCommand(strQuery, objConn)
        Using (objCommand)
            Try
                objDR = objCommand.ExecuteReader()
                Using objDR
                    booTableExists = objDR.HasRows()
                End Using
            Catch ex As Exception
            End Try
        End Using

        Return booTableExists

End Function

Leave a Reply