首页 文章

SQLite架构信息元数据

提问于
浏览
35

我需要在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) 对我不起作用,因为我没有表名 . 我想获取数据库中的所有列元数据 .

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

7 回答

  • 1

    你基本上已经在你的问题中命名了解决方案 .

    要获取表(和视图)列表,请查询sqlite_master

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

    (见the SQLite FAQ

    要获取有关特定表中列的信息,请按the SQLite PRAGMA documentation中的说明使用 PRAGMA table_info(table-name); .

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

  • 4

    有“.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
    

    希望,它在某种程度上有所帮助......

  • 4

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

  • 70

    另一个有用的技巧是首先从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',因为记录限制语法似乎从db到db不等 . 此外,一个好的数据库将优化这个永远错误的条款 .

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

  • 9

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

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

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

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

  • 0

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

    • notnull (如果列具有 NOT NULL 约束,则为 1

    • dflt_valueNULL 如果没有默认值)

    • pk1 如果列是表的主键,否则为 0

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

  • 2

    这是一个古老的问题,但由于它被查看的次数我们正在添加问题,原因很简单大多数答案告诉你如何在SQLite数据库中找到TABLE名称你在表名时做什么不在数据库中吗?我们的应用程序正在发生这种情况,因为我们正在以编程方式创建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();
        }
    }
    

相关问题