2009-05-30 22 views
35

Para patadas que estoy escribiendo una herramienta "documentación del esquema" que genera una descripción de las tablas y relaciones en una base de datos. Actualmente estoy haciendo ajustes para trabajar con SQLite.Encuentra nombres de columna en la tabla SQLite vacío

He logrado extraer los nombres de todas las tablas en una base de datos SQLite mediante una consulta en la tabla sqlite_master. Para cada nombre de la tabla, entonces me llamas más allá de un simple consulta

select * from <table name> 

, a continuación, utilizar los sqlite3_column_count() y sqlite3_column_name() API para recoger los nombres de columna, que me alimento más a sqlite3_table_column_metadata() para obtener información adicional. Lo suficientemente simple, ¿verdad?

El problema es que sólo funciona para las tablas que no están vacías. Es decir, el sqlite_column_*() API sólo son válidos si sqlite_step() ha vuelto SQLITE_ROW, lo cual no es el caso de mesas vacías.

Así que la pregunta es, ¿cómo puedo descubrir nombres de columna para mesas vacías? O, de manera más general, ¿hay una forma mejor de obtener este tipo de información de esquema en SQLite?

Siento que debe haber otra mesa oculta sqlite_xxx al acecho en algún lugar que contenga esta información, pero hasta ahora no ha podido encontrarla.

+2

gracias a todos. Pensé erróneamente que la interfaz PRAGMA era solo para el cliente de línea de comandos 'sqlite3'. –

Respuesta

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

Parece que funciona en la línea de comandos: ¿cómo puedo lograr el mismo efecto programáticamente? –

+4

@pragmanatu es su apodo una coincidencia? :) –

+0

Gracias - esto funcionó como un encanto y es mucho más simple que lo que estaba haciendo. ¡Aclamaciones! –

3

La declaración PRAGMA sugerido por @pragmanatu funciona bien a través de cualquier interfaz de programación, también. Alternativamente, la columna sql de sqlite_master tiene la declaración SQLCREATE TABLE &c &c que describe la tabla (pero, tendría que analizar eso, así que creo que PRAGMA table_info es más ... pragmático ;-).

10

ejecutar la consulta:

PRAGMA table_info(your_table_name); 

Documentation

3

ejecutar esta consulta

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

Puede probarlo al online sqlite engine

+0

Intenté esto, no funcionó. – xApple

+0

¡de esta manera es lo mejor!Si no conoce el nombre de la columna 'rowid', sugiero usar:' SELECT t. * FROM (SELECT 1) LEFT JOIN table AS AS LIMIT 1' – conca

4

PRAGMA table_info(your_table_name); no funciona en HTML5 SQLite.

Aquí es un pequeño fragmento de JavaScript HTML5 SQLite que consiga los nombres de las columnas de your_table_name aunque su vacío. Espero que sea útil.

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

Parece que su tabla tiene más de una columna, columnas 2 - n no se procesa debido al espacio en blanco inicial. Esto se puede solucionar llamando a la función 'trim()' en la cadena (o implementándola usted mismo para los navegadores que aún no admiten 'trim()'). Al llamar a la función anterior en una tabla (Persona) con un campo ID y Nombre, se devuelve '[" id "," "]'. – legacybass

0

Si está demandando SQLite 3.8.3 o posterior (es compatible con la cláusula), esta consulta recursiva debe trabajar para cuadros básicos. En 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); 
Cuestiones relacionadas