2009-05-30 27 views
35

对于踢我写一个“模式文档”工具,生成一个数据库中的表和关系的描述。我目前正在使它与SQLite兼容。在空表中查找SQLite列名

我设法通过sqlite_master表上的查询提取SQLite数据库中的所有表的名称。对于每个表的名字,然后我火了一个简单的

select * from <table name> 

查询,然后使用sqlite3_column_count()sqlite3_column_name() API来收集列名,我还喂sqlite3_table_column_metadata()以获得更多信息。很简单,对吗?

问题是,它只适用于非空的表。也就是说,sqlite_column_*() API仅在sqlite_step()已返回SQLITE_ROW时才有效,对于空表而言情况并非如此。

所以问题是,我如何发现空表的列名?或者,更一般地说,是否有更好的方式在SQLite中获得这种类型的模式信息?

我觉得必须有另一个隐藏的sqlite_xxx表潜伏着某个地方包含此信息,但到目前为止还没有找到它。

+2

感谢所有。我错误地认为PRAGMA接口仅适用于`sqlite3`命令行客户端。 – 2009-05-30 04:07:05

回答

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

看起来像是在命令行上工作 - 我如何以编程方式实现相同的效果? – 2009-05-30 02:59:02

+4

@pragmanatu是你的昵称巧合? :) – 2009-05-30 03:30:32

+0

谢谢 - 这就像一个魅力工作,比我所做的更简单。干杯! – 2009-05-30 04:05:31

3

@pragmanatu建议的PRAGMA语句也可以在任何编程接口中正常工作。或者,sqlite_mastersql列的SQL语句CREATE TABLE &c &c描述了该表(但是,您必须解析该表,因此我认为PRAGMA table_info更实用;-)。

10

执行查询:

PRAGMA table_info(your_table_name); 

Documentation

4

PRAGMA table_info(your_table_name);尝试在HTML5 SQLite不工作。

这是一个小型的HTML5 SQLite JavaScript代码片段,它从your_table_name获取列名称,即使它是空的。希望它有帮助。

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

如果您起诉SQLite 3.8.3或更高版本(支持WITH子句),则此递归查询应该适用于基本表。在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);