Trouver des noms de colonne SQLite dans la Table vide

pour le plaisir, j'écris un outil de "documentation schema" qui génère une description des tables et des relations dans une base de données. Je suis en train de le shimming pour travailler avec SQLite.

j'ai réussi à extraire les noms de toutes les tables dans une base de données SQLite via une requête sur le sqlite_master tableau. Pour chaque nom de table, je tire alors un simple

select * from <table name>

requête, puis utilisez le sqlite3_column_count() et sqlite3_column_name() Api pour recueillir les noms de colonne, qui je le nourrir par la suite sqlite3_table_column_metadata() pour obtenir des informations supplémentaires. Assez Simple, non?

Le problème est qu'il ne fonctionne que pour les tables qui ne sont pas vides. Qui est, le sqlite_column_*() les API ne sont valides que si sqlite_step() est de retour SQLITE_ROW, qui n'est pas le cas pour les tables vides.

alors la question Est, Comment puis-je découvrir les noms de colonne pour les tables vides? Ou, plus généralement, est-il une meilleure façon d'obtenir ce type d'informations de schéma dans SQLite?

je me sens comme il doit être cachée sqlite_xxx table rôdant quelque part contenant cette information, mais jusqu'à présent n'ont pas été en mesure de le trouver.

36
demandé sur Drew Hall 2009-05-30 06:51:33

6 réponses

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
62
répondu 2009-05-30 02:56:24

Exécution de la requête:

PRAGMA table_info( your_table_name );

Documentation

10
répondu Nick Dandoulakis 2009-05-30 03:17:33

PRAGMA table_info( your_table_name ); ne fonctionne pas dans HTML5 SQLite.

voici un petit extrait de JavaScript HTML5 SQLite qui obtient les noms des colonnes de votre_name même si elle est vide. Espérons que c'est 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, '').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;
});
4
répondu GeekTantra 2011-12-08 12:00:52

exécutez cette requête

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

Vous pouvez essayer en ligne moteur sqlite

4
répondu user941581 2013-09-17 20:19:01

PRAGMA déclaration suggérée par @pragmanatu fonctionne très bien à travers n'importe quelle interface programmatique, aussi. Alternativement, le sql colonne sqlite_master a SQL déclaration CREATE TABLE &c &c qui décrit la table (mais, vous auriez à analyser qui, je pense donc que PRAGMA table_info c'est plus... pragmatique.)-;

3
répondu Alex Martelli 2009-05-30 03:09:54

si vous poursuivez SQLite 3.8.3 ou plus tard (supporte la clause WITH), cette requête récursive devrait fonctionner pour les tables de base. On 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);
0
répondu 2014-06-19 18:08:12