2009-05-30 72 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);