2010-10-08 20 views
11

Nel codice seguente, pathToNonDatabase è il percorso di un semplice file di testo, non un vero database SQLite. Speravo che sqlite3_open lo rilevasse, ma non lo è (db non è NULL e result è SQLITE_OK). Quindi, come rilevare che un file non è un database SQLite valido?Come stabilire se il file di database sqlite è valido o meno

sqlite3 *db = NULL; 
int result = sqlite3_open(pathToNonDatabase, &db); 

if((NULL==db) || (result!=SQLITE_OK)) { 
    // invalid database 
} 

risposta

12

sqlite apre i database pigramente. Basta fare qualcosa subito dopo l'apertura che richiede che sia un database.

Il migliore è probabilmente pragma schema_version;.

  • Questo rapporto 0 se il database non è stato creato (ad esempio, un file vuoto). In questo caso, è sicuro lavorare con (ed eseguire CREATE TABLE, ecc.)
  • Se il database è stato creato, restituirà quante revisioni lo schema ha attraversato. Questo valore potrebbe non essere interessante, ma non è zero.
  • Se il file esiste e non è un database (o vuoto), si verificherà un errore.

Se si desidera un controllo un po 'più approfondito, è possibile utilizzare pragma quick_check;. Questo è un controllo di integrità più leggero, che salta controllando che il contenuto delle tabelle sia allineato con gli indici. Può essere ancora molto lento.

Evitare integrity_check. Non solo controlla ogni pagina, ma verifica i contenuti delle tabelle rispetto agli indici. Questo è positivamente glaciale su un grande database.

+1

"pragma schema_version;" a volte l'errore "database è bloccato". Darò il "pragma quick_check;" una prova –

+1

Se il tuo database è bloccato, è bloccato. Tutto fallirà. Riprova quando non è bloccato. :) –

+0

Hai ragione. Tutto fallisce quando il database è bloccato. Anche seleziona. Nel mio caso volevo determinare se il file era un database Sqlite3. Se ottengo l'errore "database è bloccato", penso che sia sicuro assumere che il file sia un database Sqlite3. –

2

Penso che un integrity_check pragma poteva farlo.

+0

Attenzione; questo può essere molto lento se il tuo database è grande. –

4

Per chiunque abbia bisogno di fare questo in C# con System.Data.SQLite è possibile avviare una transazione, e poi subito a rotolare indietro come segue: -

private bool DatabaseIsValid(string filename) 
    { 
     using (SQLiteConnection db = new SQLiteConnection(@"Data Source=" + filename + ";FailIfMissing=True;")) 
     { 
      try 
      { 
       db.Open(); 
       using (var transaction = db.BeginTransaction()) 
       { 
        transaction.Rollback(); 
       } 
      } 
      catch (Exception ex) 
      { 
       log.Debug(ex.Message, ex); 
       return false; 
      } 
     } 
     return true; 
    } 

Se il file non è un database valido il seguito da SQLiteException viene generato - il file è crittografato o non è un database (System.Data.SQLite.SQLiteErrorCode.NotADb). Se non si utilizzano database crittografati, questa soluzione dovrebbe essere sufficiente. (Per la versione 1.0.81.0 di System.Data.SQLite era necessario solo 'db.Open()', ma quando ho eseguito l'aggiornamento alla versione 1.0.91.0 ho dovuto inserire il blocco interno interno per farlo funzionare.

Problemi correlati