在空表中查找 SQLite 列名

Posted

技术标签:

【中文标题】在空表中查找 SQLite 列名【英文标题】:Find SQLite Column Names in Empty Table 【发布时间】:2010-10-30 01:20:19 【问题描述】:

我正在编写一个“模式文档”工具,用于生成数据库中表和关系的描述。我目前正在调整它以与 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 表潜伏在某个包含此信息的地方,但到目前为止还没有找到它。

【问题讨论】:

谢谢大家。我误以为 PRAGMA 接口只适用于sqlite3 命令行客户端。 【参考方案1】:

如果您使用 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);

【讨论】:

【参考方案2】:

执行这个查询

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

您可以在online sqlite engine尝试一下

【讨论】:

这种方式最好!如果您不知道我建议使用的rowid 列的名称:SELECT t.* FROM (SELECT 1) LEFT JOIN table AS t LIMIT 1 @conca 的建议让我找到了我需要的解决方案,即将普通查询与“空表的备份查询”结合起来。 SELECT * from 'table' UNION SELECT t.* FROM (SELECT 1) LEFT JOIN 'table' AS t;" 这允许单个查询无论表是否有数据都可以工作,并且我可以访问列名。非常感谢!!!【参考方案3】:

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;
);

【讨论】:

看起来如果您的表有多个列,则第 2 - n 列由于前导空格而不会得到处理。这可以通过在字符串上调用trim() 函数来解决(或者为尚不支持trim() 的浏览器自己实现它)。在带有 ID 和 Name 字段的表(Person)上调用上述函数返回["id", ""] 这是一个主要的 SQL“注入”风险。【参考方案4】:

执行查询:

PRAGMA table_info( your_table_name );

Documentation

【讨论】:

【参考方案5】:

@pragmanatu 建议的 PRAGMA 语句也可以通过任何编程接口正常工作。或者,sqlite_mastersql 列具有描述该表的 SQL 语句 CREATE TABLE &amp;c &amp;c(但是,您必须对其进行解析,所以我认为 PRAGMA table_info 更...实用;-) .

【讨论】:

【参考方案6】:
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

【讨论】:

看起来可以在命令行上运行——我怎样才能以编程方式实现相同的效果? 谢谢——这就像一个魅力 & 比我做的要简单得多。干杯! @Drew Hall 这也可以作为以编程方式执行的查询,而不仅仅是从命令行。

以上是关于在空表中查找 SQLite 列名的主要内容,如果未能解决你的问题,请参考以下文章

错误:尝试在空表中首次加载表中的 Excel 数据时,Oracle Apex 中的“表名已存在”

解决oracle 11g 导出空表的方法

Oracle 11g导出空表少表的解决办法

Oracle 11g导出空表少表的解决办法

Oracle 11g导出空表少表的解决办法

Oracle 11G在用EXP 导出时,空表不能导出解决