2009-05-30 14 views
35

Per calci Sto scrivendo uno strumento "documentazione dello schema" che genera una descrizione delle tabelle e delle relazioni in un database. Attualmente lo sto facendo funzionare con SQLite.Trova nomi di colonne SQLite nella tabella vuota

Sono riuscito a estrarre i nomi di tutte le tabelle in un database SQLite tramite una query sulla tabella sqlite_master. Per ogni nome di tabella, ho poi sparare una semplice query

select * from <table name> 

, quindi utilizzare le API sqlite3_column_count() e sqlite3_column_name() per raccogliere i nomi delle colonne, che ho ulteriormente feed per sqlite3_table_column_metadata() per ottenere informazioni aggiuntive. Abbastanza semplice, giusto?

Il problema è che funziona solo per le tabelle che non sono vuote. Vale a dire, le API sqlite_column_*() sono valide solo se sqlite_step() ha restituito SQLITE_ROW, che non è il caso per le tabelle vuote.

Quindi la domanda è, come posso scoprire i nomi delle colonne per le tabelle vuote? O, più in generale, c'è un modo migliore per ottenere questo tipo di informazioni sullo schema in SQLite?

Mi sento come se ci fosse un altro tavolo nascosto sqlite_xxx in agguato da qualche parte contenente queste informazioni, ma finora non sono stato in grado di trovarlo.

+2

Grazie a tutti. Ho erroneamente pensato che l'interfaccia PRAGMA fosse solo per il client della riga di comando 'sqlite3'. –

risposta

61
sqlite> .header on 
sqlite> .mode column 
sqlite> create table ABC(A TEXT, B VARCHAR); 
sqlite> pragma table_info(ABC); 
cid   name  type  notnull  dflt_value pk 
---------- ---------- ---------- ---------- ---------- ---------- 
0   A   TEXT  0      0 
1   B   VARCHAR  0      0 
+4

Sembra che funzioni sulla riga di comando: come posso ottenere lo stesso effetto in modo programmatico? –

+4

@pragmanatu è il tuo soprannome una coincidenza? :) –

+0

Grazie - ha funzionato come un fascino ed è molto più semplice di quello che stavo facendo. Saluti! –

3

Il PRAGMA dichiarazione suggerito da @pragmanatu funziona bene attraverso qualsiasi interfaccia di programmazione, anche. In alternativa, la colonna sql diha la dichiarazione SQLCREATE TABLE &c &c che descrive la tabella (ma, dovresti analizzarla, quindi penso che PRAGMA table_info sia più ... pragmatico ;-).

10

eseguire la query:

PRAGMA table_info(your_table_name); 

Documentation

3

Eseguire questa query

select * from (select "") left join my_table_to_test b on -1 = b.rowid; 

Si può provare a online sqlite engine

+0

Ho provato questo, non ha funzionato. – xApple

+0

in questo modo è il migliore!Se non conosci il nome della colonna 'rowid', ti suggerisco di usare:' SELECT t. * FROM (SELECT 1) LEFT JOIN table AS t LIMIT 1' – conca

4

PRAGMA table_info(your_table_name); non funziona in HTML5 SQLite.

Ecco un piccolo Snippet JavaScript SQLite HTML5 che ottiene i nomi delle colonne da your_table_name anche se è vuoto. Spero che sia utile.

tx.executeSql('SELECT name, sql FROM sqlite_master WHERE type="table" AND name = "your_table_name";', [], function (tx, results) { 
    var columnParts = results.rows.item(0).sql.replace(/^[^\(]+\(([^\)]+)\)/g, '$1').split(','); 
    var columnNames = []; 
    for(i in columnParts) { 
    if(typeof columnParts[i] === 'string') 
     columnNames.push(columnParts[i].split(" ")[0]); 
    } 
    console.log(columnNames); 
    ///// Your code which uses the columnNames; 
}); 
+0

Sembra che la tua tabella abbia più di una colonna, colonne 2 - n non viene elaborato a causa degli spazi bianchi iniziali. Questo può essere risolto chiamando la funzione 'trim()' sulla stringa (o implementandola tu stesso per i browser che non supportano ancora 'trim()'). Chiamando la funzione precedente su una tabella (Persona) con un campo ID e Nome restituisce '[" id "," "]'. – legacybass

0

Se hanno fatto causa SQLite 3.8.3 o successiva (supporta la clausola), questa query ricorsive dovrebbe funzionare per le tabelle di base. Su CTAS, YMMV.

WITH 
    Recordify(tbl_name, Ordinal, Clause, Sql) 
AS 
    (
    SELECT 
     tbl_name, 
     0, 

     '', 
     Sql 
    FROM 
     (
     SELECT 
      tbl_name, 
      substr 
      (
      Sql, 
      instr(Sql, '(') + 1, 
      length(Sql) - instr(Sql, '(') - 1 
      ) || ',' Sql 
     FROM 
      sqlite_master 
     WHERE 
      type = 'table' 
     ) 
    UNION ALL 
    SELECT 
     tbl_name, 
     Ordinal + 1, 
     trim(substr(Sql, 1, instr(Sql, ',') - 1)), 
     substr(Sql, instr(Sql, ',') + 1) 
    FROM 
     Recordify 
    WHERE 
     Sql > '' 
     AND lower(trim(Sql)) NOT LIKE 'check%' 
     AND lower(trim(Sql)) NOT LIKE 'unique%' 
     AND lower(trim(Sql)) NOT LIKE 'primary%' 
     AND lower(trim(Sql)) NOT LIKE 'foreign%' 
     AND lower(trim(Sql)) NOT LIKE 'constraint%' 
    ), 
    -- Added to make querying a subset easier. 
    Listing(tbl_name, Ordinal, Name, Constraints) 
AS 
    (
    SELECT 
     tbl_name, 
     Ordinal, 
     substr(Clause, 1, instr(Clause, ' ') - 1), 
     trim(substr(Clause, instr(Clause, ' ') + 1)) 
    FROM 
     Recordify 
    WHERE 
     Ordinal > 0 
    ) 
SELECT 
    tbl_name, 
    Ordinal, 
    Name, 
    Constraints 
FROM 
    Listing 
ORDER BY 
    tbl_name, 
    lower(Name); 
Problemi correlati