How do I check in SQLite whether a table exists?
如何可靠地签入sqlite,检查是否存在特定的用户表?
我不会要求不可靠的方法,比如检查表上的"select*"是否返回错误(这是一个好主意吗?).
原因如下:
在我的程序中,如果一些表不存在,我需要创建它们,然后填充它们。
如果它们已经存在,我需要更新一些表。
我是否应该采用其他路径来表示所讨论的表已经被创建了——例如,通过在磁盘上的程序初始化/设置文件中创建/放置/设置某个标志或其他方式?
或者我的方法有意义吗?
我错过了FAQ条目。
无论如何,为了将来参考,完整的查询是:
1 | SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}'; |
其中,
参考文档部分:数据库文件格式。2.6。SQL数据库架构的存储
如果您使用的是sqlite 3.3+版本,那么您可以轻松地创建一个表:
1 | create table if not exists TableName (col1 typ1, ..., colN typN) |
同样,只有当表存在时,才能使用以下方法删除表:
1 | drop table if exists TableName |
一种变化是使用select count(*)而不是select name,即
1 | SELECT count(*) FROM sqlite_master WHERE type='table' AND name='table_name'; |
如果表不存在,则返回0;如果存在,则返回1。这在编程中可能很有用,因为数值结果处理起来更快/更容易。下面说明了如何在Android中使用带参数的sqliteDatabase、cursor和rawquery来实现这一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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; } |
你可以试试:
1 | SELECT name FROM sqlite_master WHERE name='table_name' |
如果您收到"table already exists"错误,请按以下方式更改SQL字符串:
1 | CREATE table IF NOT EXISTS table_name (para1,para2); |
这样就可以避免异常。
sqlite表名不区分大小写,但默认情况下比较区分大小写。为了在所有情况下都能正常工作,您需要添加
1 | SELECT name FROM sqlite_master WHERE type='table' AND name='table_name' COLLATE NOCASE |
用途:
1 | PRAGMA table_info(your_table_name) |
如果结果表是空的,那么
文档:
PRAGMA schema.table_info(table-name);
This pragma returns one row for each column in the named table. Columns in the result set include the column name, data type, whether or not the column can be NULL, and the default value for the column. The"pk" column in the result set is zero for columns that are not part of the primary key, and is the index of the column in the primary key for columns that are part of the primary key.
The table named in the table_info pragma can also be a view.
实例输出:
1 2 3 4 | cid|name|type|notnull|dflt_value|pk 0|id|INTEGER|0||1 1|json|JSON|0||0 2|name|TEXT|0||0 |
看到这个:
1 2 3 | SELECT name FROM sqlite_master WHERE type='table' ORDER BY name; |
如果您使用的是fmdb,我想您可以导入fmdatabaseadditions并使用bool函数:
1 | [yourfmdbDatabase tableExists:tableName]. |
如果表存在,则以下代码返回1;如果表不存在,则返回0。
1 | SELECT CASE WHEN tbl_name ="name" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name ="name" AND type ="table" |
注意,要检查临时数据库中是否存在表,必须使用
1 | SELECT name FROM sqlite_temp_master WHERE type='table' AND name='table_name'; |
使用此代码:
1 | SELECT name FROM sqlite_master WHERE type='table' AND name='yourTableName'; |
如果返回的数组计数等于1,则表示该表存在。否则它就不存在了。
下面是我使用的函数:
给定一个sqldatabase对象=db
1 2 3 4 5 6 7 8 | public boolean exists(String table) { try { db.query("SELECT * FROM" + table); return true; } catch (SQLException e) { return false; } } |
我在C中发现的最可靠的方法是使用最新的sqlite net pcl nuget包(1.5.231),它使用sqlite 3,如下所示:
1 2 3 4 5 | var result = database.GetTableInfo(tableName); if ((result == null) || (result.Count == 0)) { database.CreateTable<T>(CreateFlags.AllImplicit); } |
使用
1 | SELECT 1 FROM table LIMIT 1; |
以防止读取所有记录。
在我看来,使用简单的select查询是相当可靠的。最重要的是,它可以在许多不同的数据库类型(sqlite/mysql)中检查表的存在。
1 | SELECT 1 FROM table; |
当您可以使用其他可靠的机制来确定查询是否成功时(例如,通过qt中的qsqlquery查询数据库),这是有意义的。
您可以编写以下查询来检查表是否存在。
1 | SELECT name FROM sqlite_master WHERE name='table_name' |
这里的"表名"是您创建的表名。例如
1 | CREATE TABLE IF NOT EXISTS country(country_id INTEGER PRIMARY KEY AUTOINCREMENT, country_code TEXT, country_name TEXT)" |
并检查
1 | SELECT name FROM sqlite_master WHERE name='country' |
这是我的sqlite cordova代码:
1 2 3 4 5 6 7 8 | get_columnNames('LastUpdate', function (data) { if (data.length > 0) { // In data you also have columnNames console.log("Table full"); } else { console.log("Table empty"); } }); |
另一个是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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。
1 2 3 4 5 6 | select case when exists (select 1 from sqlite_master WHERE type='table' and name = 'your_table') then 1 else 0 end as TableExists |
类cphoenix database():
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
注意:这在我的Mac上使用的是python 3.7.1。