55

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

在 MySQL 中,我可以通过对 database 的 SQL 查询来获取这些信息INFORMATION_SCHEMA。但是 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)不适合我,因为我没有表名。我想获取数据库中的所有列元数据。

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

4

7 回答 7

94

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

要获取表(和视图)列表,请查询 sqlite_master,如下所示

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

(参见SQLite 常见问题解答

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

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

于 2011-07-07T22:13:27.333 回答
19

最新版本的 SQLite 允许您现在选择 PRAGMA 结果,这使得这很容易:

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

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

David Garoutte在这里回答了这个问题,但是这个 SQL 应该执行得更快,并且列是按模式排序的,而不是按字母顺序排列的。

注意table_info还包含

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

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

于 2018-11-05T18:47:46.607 回答
11

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

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

于 2011-06-23T22:49:43.037 回答
4

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

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

在蟒蛇

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

朱拉伊

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

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

于 2012-12-22T17:05:14.433 回答
2

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

于 2011-10-24T02:17:25.480 回答
2

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

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

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

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

于 2015-04-14T15:49:49.127 回答
0

这是一个老问题,但由于它被查看的次数,我们添加到这个问题中的原因很简单,大多数答案都告诉你如何在 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();
    }
}
于 2018-04-29T02:21:55.887 回答