如何在SQLite中检查表是否存在?

如何在SQLite中,可靠地,检查特定的用户表是否存在?

我不是在要求不可靠的方法,比如检查表上的“选择*”是否返回错误(这是个好主意吗?)。

原因是这样的:

在我的程序中,我需要创建然后填充一些表,如果它们不存在的话。

如果它们已经存在,我需要更新一些表。

我是否应该采取其他路径来表示有问题的表已经创建-例如,通过在磁盘上的程序初始化/设置文件中创建/放置/设置某个标志或其他方式?

我的方法有意义吗?

557612 次浏览

请参阅SQLite FAQ中的(7)如何列出SQLite数据库中包含的所有表/索引

SELECT name FROM sqlite_masterWHERE type='table'ORDER BY name;

你可以试试:

SELECT name FROM sqlite_master WHERE name='table_name'

我错过了FAQ。

无论如何,为了将来参考,完整的查询是:

SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';

其中{table_name}是要检查的表的名称。

供参考的文档部分:数据库文件格式。2.6。SQL数据库模式的存储

  • 这将返回具有指定名称的表列表;也就是说,游标的计数为0(不存在)或计数为1(确实存在)

如果您使用的是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 NAME。

SELECT count(*) FROM sqlite_master WHERE type='table' AND name='table_name';

如果表不存在,这将返回0,如果存在,则返回1。这在您的编程中可能很有用,因为数字结果更快/更容易处理。以下说明了您如何在Android中使用SQLiteDatabase、光标、带参数的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;}

如果你使用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不存在。

文档:

PRAGMAschema.table_info(table-name);

此Pragma为命名表中的每一列返回一行。结果集中的列包括列名、数据类型、该列是否可以为NULL以及该列的默认值。对于不属于主键的列,结果集中的“pk”列为零;对于属于主键的列,结果集中的“pk”列是主键中列的索引。

在table_info中命名的表也可以是视图。

输出示例:

cid|name|type|notnull|dflt_value|pk0|id|INTEGER|0||11|json|JSON|0||02|name|TEXT|0||0

使用

SELECT 1 FROM table LIMIT 1;

以防止读取所有记录。

如果您收到“表已存在”错误,请在SQL字符串中进行更改,如下所示:

CREATE table IF NOT EXISTS table_name (para1,para2);

这样你就可以避免例外。

这是我的SQLite科尔多瓦代码:

get_columnNames('LastUpdate', function (data) {if (data.length > 0) { // In data you also have columnNamesconsole.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(','); ///// RegExfor (i in columnParts) {if (typeof columnParts[i] === 'string')columnNames.push(columnParts[i].split(" ")[0]);};callback(columnNames);}else callback(columnNames);});});}

我想我会把我的2美分放在这个讨论中,即使它相当古老…如果表存在,此查询返回标量1,否则返回0。

selectcase when exists(select 1 from sqlite_master WHERE type='table' and name = 'your_table')then 1else 0end 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 = dbnameself.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 Falseelse:return True

注意:这现在在我的Mac上使用Python 3.7.1工作

我现在在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;}

您还可以使用db元数据来检查表是否存在。

DatabaseMetaData md = connection.getMetaData();ResultSet resultSet = md.getTables(null, null, tableName, null);if (resultSet.next()) {return true;}

我的首选方法:

SELECT "name" FROM pragma_table_info("table_name") LIMIT 1;

如果您获得行结果,则表存在。这(对我来说)比检查sqlite_master更好,因为它还会检查附加数据库和临时数据库。

如果您使用python文件运行它并显然使用sqlite3。打开命令提示符或bash无论您使用什么

  1. python3file_name.py第一个编写sql代码的位置。
  2. 然后运行SQLITE3file_name.db
  3. .表格此命令将给出表(如果存在)。

我想补充迭戈·贝莱斯关于0号声明的回答。

https://sqlite.org/pragma.html开始,我们得到了一些有用的函数,可以返回有关我们数据库的信息。在这里我引用以下内容:

例如,有关索引中列的信息可以使用index_info的语用来读取,如下所示:

PRAGMA index_info('idx52');

或者,可以使用以下方式阅读相同的内容:

SELECT * FROM pragma_index_info('idx52');

表值函数格式的优点是查询可以只返回PRAGMA列的子集,可以包含WHERE子句,可以使用聚合函数,并且表值函数可以只是连接中的几个数据源之一。

Diego的回答给了PRAGMA table_info(table_name)一个选项,但这在您的其他查询中没有多大用处。

因此,要回答OPs问题并改进Diegos的答案,您可以这样做

SELECT * FROM pragma_table_info('table_name');

甚至更好,

SELECT name FROM pragma_table_list('table_name');

如果你想模仿普尔鲁泽斯的最高投票答案。

如果你处理大桌子,我用Python和Sqlite做了一个简单的hack,你可以用任何其他语言做类似的想法

第1步:不要在创建表命令中使用(如果不存在)

您可能知道,如果您运行此命令,如果您之前已经创建了表,并且想要再次创建它,则会出现异常,但这将引导我们进入第二步。

第2步:使用尝试除了(或尝试捕获其他语言)来处理最后一个异常

在这里,如果您之前没有创建表,则尝试 case将继续,但如果您已经这样做了,您可以将do您的流程放在除了 case,您将知道您已经创建了表。

以下是代码:

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包中的函数dbExistsTable()为R程序员简化了这个问题。请参阅下面的示例:

library(DBI)con <- dbConnect(RSQLite::SQLite(), ":memory:")# let us check if table iris exists in the databasedbExistsTable(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