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
(数据类型,如integer
或text
),
notnull
(1
如果列有NOT NULL
约束)
dflt_value
(NULL
,如果没有默认值)
pk
(1
如果列是表的主键,否则0
)
RTFM:https://www.sqlite.org/pragma.html#pragma_table_info
【讨论】:
注意pk
是主键索引。对于主键中有一列的表,那么该列 pk
的值将是 1
(如答案所述)。但是,如果主键有多列,则pk
的值可以是2
、3
等等。【参考方案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 表的元数据中得到?