SQLite 模式信息元数据

Posted

技术标签:

【中文标题】SQLite 模式信息元数据【英文标题】:SQLite Schema Information Metadata 【发布时间】:2011-06-23 21:14:41 【问题描述】:

我需要在 SQLite 数据库中获取列名及其表。我需要的是一个包含 2 列的结果集:table_name | column_name

mysql 中,我可以通过对数据库 INFORMATION_SCHEMA 的 SQL 查询来获取此信息。然而 SQLite 提供了表sqlite_master

sqlite> create table students (id INTEGER, name TEXT);
sqlite> select * from sqlite_master;
  table|students|students|2|CREATE TABLE students (id INTEGER, name TEXT)

这会导致 DDL 构造查询 (CREATE TABLE),这对我没有帮助,我需要对其进行解析以获取相关信息。

我需要获取表列表并将它们与列连接,或者只获取列和表名列。所以PRAGMA table_info(TABLENAME) 不适合我,因为我没有表名。我想获取数据库中的所有列元数据。

有没有更好的方法通过查询数据库来获取该信息作为结果集?

【问题讨论】:

【参考方案1】:

您基本上已经在问题中命名了解决方案。

要获取表(和视图)的列表,请按如下方式查询 sqlite_master

SELECT name, sql FROM sqlite_master
WHERE type='table'
ORDER BY name;

(见the SQLite FAQ)

要获取有关特定表中列的信息,请使用PRAGMA table_info(table-name);,如the SQLite PRAGMA documentation 中所述。

我不知道有什么方法可以让表名|列名作为单个查询的结果返回。我不相信 SQLite 支持这一点。您最好的选择可能是同时使用这两种方法来返回您正在寻找的信息 - 首先使用 sqlite_master 获取表列表,然后使用 PRAGMA table_info() 遍历它们以获取它们的列。

【讨论】:

pragma 不提供列数据。 .schema 确实如此,我已经将其结果粘贴到了问题中。我已经意识到这一点。我正在寻找方法。 其实PRAGMA table_info()确实会返回列数据,只要你有表名,你可以从sqlite_master获取。不过,我确实意识到,您正在寻找仅返回 tablename|columname 的一步解决方案,而我建议的是一种可以在某种程序中使用的解决方法(两个步骤)。虽然我的回答并没有真正引入任何新信息,但我相信它可能会对某人有所帮助。 AFAIK没有更好的方法......对不起。但我不介意被证明是错误的:-) 我的错。是的 pragma 给出了这个,但是如果我有 100 个表,首先我应该从 sqlite_master 获取表列表,然后我应该执行 100 个 pragma 请求,我不想这样做。 是的,就是这个意思,你需要使用 sqlite_master 和 prama table_info 的组合;这是正确的方法。 此答案为您提供架构转储,而不是请求的tablename|columnName。事实证明table_info pragma 是可连接的,所以这是一个简单的选择:见***.com/a/53160348/1268016【参考方案2】:

最新版本的 SQLite 允许您select against PRAGMA results now,这让这很容易:

SELECT 
  m.name as table_name, 
  p.name as column_name
FROM 
  sqlite_master AS m
JOIN 
  pragma_table_info(m.name) AS p
ORDER BY 
  m.name, 
  p.cid

其中p.cid 保存 CREATE TABLE 语句的列顺序,零索引。

David Garoutte 回答了这个here,但是这个 SQL 应该执行得更快,并且列是按架构排序的,而不是按字母顺序。

注意table_info也包含

type(数据类型,如integertext), notnull1 如果列有NOT NULL 约束) dflt_valueNULL,如果没有默认值) pk1如果列是表的主键,否则0

RTFM:https://www.sqlite.org/pragma.html#pragma_table_info

【讨论】:

注意pk是主键索引。对于主键中有一列的表,那么该列 pk 的值将是 1 (如答案所述)。但是,如果主键有多列,则pk的值可以是23等等。【参考方案3】:

有“.tables”和“.schema [table_name]”命令可以为您从“select * from sqlite_master;”得到的结果提供一种分离的版本

还有“pragma table_info([table_name]);”命令以获得更好的解析结果而不是构造查询:


sqlite> .tables
students
sqlite> .schema students
create table students(id INTEGER, name TEXT);
sqlite> pragma table_info(students);
0|id|INTEGER|0||0
1|name|TEXT|0||0

希望,它在一定程度上有所帮助......

【讨论】:

但我认为.tables 是一个特定于shell 的函数,对吧?我需要从 SQL 界面执行它。 是的,我想是的。无论如何,您需要实现一个解析器:)【参考方案4】:

另一个有用的技巧是首先从 sqlite_master 获取所有表名。

然后对于每一个,触发一个查询“select * from t where 1 = 0”。如果您分析生成的查询的结构 - 取决于您调用它的语言/api - 您将获得描述列的丰富结构。

在python中

c = ...db.cursor()
c.execute("select * from t where 1=0");
c.fetchall();
print c.description;

朱拉杰

PS。我习惯使用'where 1=0',因为记录限制语法似乎因数据库而异。此外,一个好的数据库会优化这个永远为假的子句。

在 SQLite 中,使用 'limit 0' 可以实现相同的效果。

【讨论】:

这很整洁【参考方案5】:

仅供参考,如果您使用的是 .Net,则可以使用 DbConnection.GetSchema 方法检索通常位于 INFORMATION_SCHEMA 中的信息。如果你有一个抽象层,你可以为所有类型的数据库使用相同的代码(注意 MySQL 似乎切换了限制数组的第一个 2 个参数)。

【讨论】:

这是用于 SQLite 的吗?这是哪个 .NET 的 SQLite 库? (不使用.net,但仍想知道) 如果你查看 www.sqlite.org 网站,你会在他们的下载部分看到他们在 System.Data.SQLite.org 上为 .NET 提供预编译二进制文件,所以它是“官方的”用于 SQLite 的 ADO.NET 适配器。 SQlite 不支持.GetSchema,抛出不支持异常。 要通过 .net 实用程序,您可能需要下载 NuGet 包【参考方案6】:

试试这个 sqlite 表模式解析器,我实现了 sqlite 表解析器来解析 php 中的表定义。

它返回完整的定义(唯一、主键、类型、精度、非空、引用、表约束...等)

https://github.com/maghead/sqlite-parser

语法遵循sqlite create table语句语法:http://www.sqlite.org/lang_createtable.html

【讨论】:

【参考方案7】:

这是一个老问题,但由于它被查看的次数,我们添加到问题中的原因很简单,大多数答案都告诉你如何在 SQLite 数据库中查找表名称 如果表名不在数据库中,您会怎么做? 这发生在我们的应用程序中,因为我们正在以编程方式创建 TABLES 因此,当 TABLE 不在数据库中或由数据库创建时,下面的代码将处理该问题。

    public void toPageTwo(View view)

    if(etQuizTable.getText().toString().equals(""))
        Toast.makeText(getApplicationContext(), "Enter Table Name\n\n"
                +"           OR"+"\n\nMake Table First", Toast.LENGTH_LONG 
   ).show();
        etQuizTable.requestFocus();
        return;
    

    NEW_TABLE = etQuizTable.getText().toString().trim();
    db = dbHelper.getWritableDatabase();
    ArrayList<String> arrTblNames = new ArrayList<>();
    Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE 
   type='table'", null);

    if (c.moveToFirst()) 
        while ( !c.isAfterLast() ) 
            arrTblNames.add( c.getString( c.getColumnIndex("name")) );
            c.moveToNext();
        
    
    c.close();
    db.close();

    boolean matchFound = false;
    for(int i=0;i<arrTblNames.size();i++) 
        if(arrTblNames.get(i).equals(NEW_TABLE)) 
            Intent intent = new Intent(ManageTables.this, TableCreate.class 
   );
            startActivity( intent );
            matchFound = true;
        
    
    if (!matchFound) 
        Toast.makeText(getApplicationContext(), "No Such Table\n\n"
                +"           OR"+"\n\nMake Table First", Toast.LENGTH_LONG 
 ).show();
        etQuizTable.requestFocus();
    

【讨论】:

以上是关于SQLite 模式信息元数据的主要内容,如果未能解决你的问题,请参考以下文章

如果一个表是自动增量的,你怎么能从一个 sqlite 表的元数据中得到?

sqlite元数据

删除 H2 数据库中的元数据(信息模式)

如何在SQLite中添加自己的PRAGMA语句来存储自定义元数据?

10-MVC设计模式

PostgreSQL:查询元数据(表 字段)信息库表导入导出命令