提问人:PoorLuzer 提问时间:10/21/2009 最后编辑:Peter MortensenPoorLuzer 更新时间:7/10/2023 访问量:591364
如何在SQLite中查看表是否存在?
How do I check in SQLite whether a table exists?
问:
我如何可靠地在SQLite中检查是否存在特定的用户表?
我不是在要求不可靠的方法,例如检查表上的“select *”是否返回错误(这甚至是一个好主意吗?
原因是这样的:
在我的程序中,我需要创建并填充一些表(如果它们尚不存在)。
如果它们已经存在,我需要更新一些表。
我是否应该采取其他路径来表示已经创建了相关表 - 例如,通过在磁盘上的程序初始化/设置文件中创建/放置/设置某个标志或其他东西?
还是我的方法有意义?
答:
请参阅 SQLite FAQ 中的 (7) 如何列出 SQLite 数据库中包含的所有表/索引:
SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
您可以尝试:
SELECT name FROM sqlite_master WHERE name='table_name'
评论
SQLiteReader reader = cmd.ExecuteReader();
dt.Load(reader)
dt
DataTable
Object reference is not an instance of an object
.Load()
SQLiteDataAdapter adapter = new SQLiteDataAdapter(cmd);
adapter.Fill(ds)
ds
DataSet
ds.Tables.Count > 0
return ds.Tables[0];
else return null
DataTable
null
dt.Rows != null
dt.Rows.Count>0
我错过了那个FAQ条目。
无论如何,为了将来参考,完整的查询是:
SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';
其中是要检查的表的名称。{table_name}
供参考的文档部分:数据库文件格式。2.6. SQL数据库模式的存储
- 这将返回具有指定名称的表列表;也就是说,游标的计数为 0(不存在)或计数为 1(存在)
评论
sqlite_schema
如果您使用的是 SQLite 版本 3.3+,则可以轻松地使用以下命令创建表:
create table if not exists TableName (col1 typ1, ..., colN typN)
同样,仅当表存在时,才能使用以下方法删除该表:
drop table if exists TableName
评论
如果表存在,则以下代码返回 1,如果表不存在,则返回 0。
SELECT CASE WHEN tbl_name = "name" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "name" AND type = "table"
评论
一种变体是使用 SELECT COUNT(*) 而不是 SELECT NAME,即
SELECT count(*) FROM sqlite_master WHERE type='table' AND name='table_name';
如果表不存在,这将返回 0,如果存在,则返回 1。这可能在您的编程中很有用,因为数值结果处理得更快/更容易。下面说明了如何在 Android 中使用带有参数的 SQLiteDatabase、Cursor 和 rawQuery 执行此操作。
boolean tableExists(SQLiteDatabase db, String tableName)
{
if (tableName == null || db == null || !db.isOpen())
{
return false;
}
Cursor cursor = db.rawQuery(
"SELECT COUNT(*) FROM sqlite_master WHERE type = ? AND name = ?",
new String[] {"table", tableName}
);
if (!cursor.moveToFirst())
{
cursor.close();
return false;
}
int count = cursor.getInt(0);
cursor.close();
return count > 0;
}
评论
COUNT(*)
SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type="table" AND name="table_name")
似乎真的将结果减少到布尔结果(0 或 1,仅此而已)
如果您使用的是 fmdb,我认为您可以导入 FMDatabaseAdditions 并使用 bool 函数:
[yourfmdbDatabase tableExists:tableName].
评论
在我看来,使用简单的 SELECT 查询非常可靠。最重要的是,它可以检查许多不同数据库类型(SQLite / MySQL)中的表是否存在。
SELECT 1 FROM table;
当您可以使用其他可靠的机制来确定查询是否成功时(例如,通过Qt中的QSqlQuery查询数据库),这是有意义的。
这是我使用的函数:
给定 SQLDatabase 对象 = db
public boolean exists(String table) {
try {
db.query("SELECT * FROM " + table);
return true;
} catch (SQLException e) {
return false;
}
}
评论
使用以下代码:
SELECT name FROM sqlite_master WHERE type='table' AND name='yourTableName';
如果返回的数组计数等于 1,则表示该表存在。否则它不存在。
SQLite 表名不区分大小写,但默认情况下比较区分大小写。要使它在所有情况下都能正常工作,您需要添加 .COLLATE NOCASE
SELECT name FROM sqlite_master WHERE type='table' AND name='table_name' COLLATE NOCASE
请注意,要检查 TEMP 数据库中是否存在表,必须使用 :sqlite_temp_master
sqlite_master
SELECT name FROM sqlite_temp_master WHERE type='table' AND name='table_name';
用:
PRAGMA table_info(your_table_name)
如果生成的表为空,则不存在。your_table_name
文档:
PRAGMA schema.table_info(表名);
此编译指示为命名表中的每一列返回一行。结果集中的列包括列名、数据类型、列是否可以为 NULL 以及列的默认值。对于不属于主键的列,结果集中的“pk”列为零,对于属于主键的列,结果是主键中列的索引。
table_info 杂注中命名的表也可以是视图。
输出示例:
cid|name|type|notnull|dflt_value|pk
0|id|INTEGER|0||1
1|json|JSON|0||0
2|name|TEXT|0||0
评论
用
SELECT 1 FROM table LIMIT 1;
以防止读取所有记录。
评论
如果出现“表已存在”错误,请在 SQL 字符串中进行更改,如下所示:
CREATE table IF NOT EXISTS table_name (para1,para2);
这样可以避免异常。
这是我的SQLite Cordova代码:
get_columnNames('LastUpdate', function (data) {
if (data.length > 0) { // In data you also have columnNames
console.log("Table full");
}
else {
console.log("Table empty");
}
});
另一个:
function get_columnNames(tableName, callback) {
myDb.transaction(function (transaction) {
var query_exec = "SELECT name, sql FROM sqlite_master WHERE type='table' AND name ='" + tableName + "'";
transaction.executeSql(query_exec, [], function (tx, results) {
var columnNames = [];
var len = results.rows.length;
if (len>0){
var columnParts = results.rows.item(0).sql.replace(/^[^\(]+\(([^\)]+)\)/g, '$1').split(','); ///// RegEx
for (i in columnParts) {
if (typeof columnParts[i] === 'string')
columnNames.push(columnParts[i].split(" ")[0]);
};
callback(columnNames);
}
else callback(columnNames);
});
});
}
我以为我会把我的 2 美分投入到这个讨论中,即使它很旧。 如果表存在,则此查询返回标量 1,否则返回标量 0。
select
case when exists
(select 1 from sqlite_master WHERE type='table' and name = 'your_table')
then 1
else 0
end as TableExists
您可以编写以下查询来检查表是否存在。
SELECT name FROM sqlite_master WHERE name='table_name'
这里的“table_name”是您创建的表名。例如
CREATE TABLE IF NOT EXISTS country(country_id INTEGER PRIMARY KEY AUTOINCREMENT, country_code TEXT, country_name TEXT)"
并检查
SELECT name FROM sqlite_master WHERE name='country'
评论
class CPhoenixDatabase():
def __init__(self, dbname):
self.dbname = dbname
self.conn = sqlite3.connect(dbname)
def is_table(self, table_name):
""" This method seems to be working now"""
query = "SELECT name from sqlite_master WHERE type='table' AND name='{" + table_name + "}';"
cursor = self.conn.execute(query)
result = cursor.fetchone()
if result == None:
return False
else:
return True
注意:这现在可以在我的装有 Python 3.7.1 的 Mac 上运行
评论
table_name
我现在在 C# 中找到的最可靠的方法,使用最新的 sqlite-net-pcl nuget 包 (1.5.231),它使用 SQLite 3,如下所示:
var result = database.GetTableInfo(tableName);
if ((result == null) || (result.Count == 0))
{
database.CreateTable<T>(CreateFlags.AllImplicit);
}
在 swift 的数据库中是否存在表,
func tableExists(_ tableName:String) -> Bool {
sqlStatement = "SELECT name FROM sqlite_master WHERE type='table' AND name='\(tableName)'"
if sqlite3_prepare_v2(database, sqlStatement,-1, &compiledStatement, nil) == SQLITE_OK {
if sqlite3_step(compiledStatement) == SQLITE_ROW {
return true
}
else {
return false
}
}
else {
return false
}
sqlite3_finalize(compiledStatement)
}
C++ 函数检查数据库和所有附加的数据库是否存在表和(可选)列。
bool exists(sqlite3 *db, string tbl, string col="1")
{
sqlite3_stmt *stmt;
bool b = sqlite3_prepare_v2(db, ("select "+col+" from "+tbl).c_str(),
-1, &stmt, 0) == SQLITE_OK;
sqlite3_finalize(stmt);
return b;
}
编辑:最近发现了sqlite3_table_column_metadata功能。因此
bool exists(sqlite3* db,const char *tbl,const char *col=0)
{return sqlite3_table_column_metadata(db,0,tbl,col,0,0,0,0,0)==SQLITE_OK;}
评论
您还可以使用数据库元数据来检查表是否存在。
DatabaseMetaData md = connection.getMetaData();
ResultSet resultSet = md.getTables(null, null, tableName, null);
if (resultSet.next()) {
return true;
}
评论
resultSet
我的首选方法:
SELECT "name" FROM pragma_table_info("table_name") LIMIT 1;
如果获得行结果,则表示该表存在。这(对我来说)比检查更好,因为它还将检查附加数据库和临时数据库。sqlite_master
如果您使用 python 文件运行它并显然使用 sqlite3。打开命令提示符或 bash 无论您正在使用什么,都使用
- python3 file_name.py编写 SQL 代码的第一个。
- 然后file_name.db运行 sqlite3。
- .table 此命令将提供表(如果存在)。
我想补充迭戈·贝莱斯(Diego Vélez)关于该声明的回答。PRAGMA
从 https://sqlite.org/pragma.html 我们得到了一些有用的函数,这些函数可以返回有关我们数据库的信息。 在这里,我引用以下内容:
例如,可以使用 index_info 编译指示读取有关索引中列的信息,如下所示:
PRAGMA index_info('idx52');
或者,可以使用以下方法读取相同的内容:
SELECT * FROM pragma_index_info('idx52');
表值函数格式的优点是查询可以只返回 PRAGMA 列的子集,可以包含 WHERE 子句,可以使用聚合函数,并且表值函数可以只是联接中的多个数据源之一。
迭戈的回答给出了一个选项,但这在您的其他查询中没有多大用处。PRAGMA table_info(table_name)
因此,要回答 OPs 问题并改进 Diegos 答案,您可以这样做
SELECT * FROM pragma_table_info('table_name');
甚至更好,
SELECT name FROM pragma_table_list('table_name');
如果你想模仿 PoorLuzers 的最高票答案。
如果你处理 Big Table,我用 Python 和 Sqlite 做了一个简单的 hack,你可以用任何其他语言提出类似的想法
第 1 步:不要在 create table 命令中使用(如果不存在)
如果您运行此命令,您可能知道,如果您之前已经创建了表,并且想要再次创建它,则该命令将出现异常,但这将引导我们进入第二步。
第 2 步:使用 try 和 except (或其他语言的 try 和 catch) 来处理最后一个异常
在这里,如果您之前没有创建表,则 try 用例将继续,但如果您已经创建了,则可以将 do your process 置于 except 大小写,您将知道您已经创建了表。
代码如下:
def create_table():
con = sqlite3.connect("lists.db")
cur = con.cursor()
try:
cur.execute('''CREATE TABLE UNSELECTED(
ID INTEGER PRIMARY KEY)''')
print('the table is created Now')
except sqlite3.OperationalError:
print('you already created the table before')
con.commit()
cur.close()
你可以使用一个简单的方法,我在 C# 和 Xamarin 中使用这个方法,
public class LoginService : ILoginService
{
private SQLiteConnection dbconn;
}
在登录服务类中,我有很多方法可以访问SQLite中的数据,我将数据存储到一个表中,登录页面 它仅在用户未登录时显示。
为此,我只需要知道表是否存在,在这种情况下,如果它存在,那是因为它有数据
public int ExisteSesion()
{
var rs = dbconn.GetTableInfo("Sesion");
return rs.Count;
}
如果该表不存在,则仅返回 0,如果该表存在,则因为它有数据,并且返回它拥有的总行数。
在模型中,我指定了表必须接收的名称,以确保其正确操作。
[Table("Sesion")]
public class Sesion
{
[PrimaryKey]
public int Id { get; set; }
public string Token { get; set; }
public string Usuario { get; set; }
}
R DBI 包中的函数为 R 程序员简化了这个问题。请参阅以下示例:dbExistsTable()
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ":memory:")
# let us check if table iris exists in the database
dbExistsTable(con, "iris")
### returns FALSE
# now let us create the table iris below,
dbCreateTable(con, "iris", iris)
# Again let us check if the table iris exists in the database,
dbExistsTable(con, "iris")
### returns TRUE
查看 C++ 中的“尝试 - 抛出 - 捕获”结构。大多数其他编程语言都有类似的结构来处理错误。
评论
如前所述,您可以使用以下查询查找表是否存在
SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';
但是,此查询将仅搜索架构main.sqlite_master
如果有一个或多个附加数据库使用
ATTACH DATABASE AS schema-name
然后,在附加的架构中将找不到表
要知道表是否存在于“main”以外的模式中,您需要遍历所有模式,例如 schema-name.sqlite_master。
为了解决这个问题,我看到 2 个选项
- 记住附加的数据库架构名称并循环访问这些名称
- 使用 sqlite 本机功能查找所有附加的数据库并遍历此列表
可以使用以下方法完成第二个选项
select * from pragma_database_list
这将返回 order、schema-name 和 DATABASE,然后您可以遍历所有 {schema-name}.sqlite_master 并查找是否存在表以及在哪个架构中(可能存在多个) ref: https://www.sqlite.org/dbpage.html#using_sqlite_dbpage_on_attach_ed_databases 是唯一的引用。我可以找到这一点,因此无法看到这是否是sqlite功能的维护部分
评论
SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type="table" AND name="table_name");