如何在SQLite中可靠地检查特定用户表是否存在?
我不是在询问像检查“select *”语句是否返回错误之类的不可靠方法(这是一个好主意吗?)。
原因如下:
在我的程序中,如果某些表不存在,我需要创建并填充它们。
如果这些表已经存在,我需要更新一些表。
是否应该采取其他方式来表示所涉及的表已经被创建 - 比如,在我的程序初始化/设置文件中创建/放置/设置某个标志或者类似操作?
还是我的方法有道理?
如何在SQLite中可靠地检查特定用户表是否存在?
我不是在询问像检查“select *”语句是否返回错误之类的不可靠方法(这是一个好主意吗?)。
原因如下:
在我的程序中,如果某些表不存在,我需要创建并填充它们。
如果这些表已经存在,我需要更新一些表。
是否应该采取其他方式来表示所涉及的表已经被创建 - 比如,在我的程序初始化/设置文件中创建/放置/设置某个标志或者类似操作?
还是我的方法有道理?
我错过了那个常见问题解答条目。
不管怎样,以后参考一下,完整的查询语句是:
SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';
其中{table_name}
是要检查的表的名称。
参考文档部分:数据库文件格式。2.6. SQL 数据库架构的存储
sqlite_schema
。旧名称仍然有效,但是答案可能需要更新以提及新名称。 - Igor Levickisqlite_schema
中进行选择;然而,sqlite_master
有效(使用Perl DBI 5.18.2的sqlite 3.39.3)。 - U. Windl如果你使用的是SQLite 3.3以上版本,你可以轻松地创建一个表:
create table if not exists TableName (col1 typ1, ..., colN typN)
同样的方式,你可以使用以下代码仅在表存在时才删除表:
drop table if exists TableName
一种变化是使用 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(*)
返回的数字很容易处理,但返回行是否存在则更容易;如果有一行,则它存在,如果没有行,则不存在。(您已经在 moveToFirst 中检查了失败,因此工作将在那一点上完成。) - dash-tom-bang你可以尝试:
SELECT name FROM sqlite_master WHERE name='table_name'
SQLiteReader reader = cmd.ExecuteReader();
中使用此命令,然后执行dt.Load(reader)
(其中dt
是DataTable
)。我发现如果找不到表格,则会在.Load()
上出现Object reference is not an instance of an object
异常。相反,使用SQLiteDataAdapter adapter = new SQLiteDataAdapter(cmd);
,然后执行adapter.Fill(ds)
,其中ds
是DataSet
。然后您可以查看ds.Tables.Count > 0
并返回ds.Tables[0]
(如果是这样,否则返回null
)。然后您可以检查该DataTable
是否为null
,如果dt.Rows != null
,并且如果dt.Rows.Count > 0
。 - vapcguy请参见SQLite FAQ中的(7)如何列出包含在SQLite数据库中的所有表/索引:
SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
使用:
PRAGMA table_info(your_table_name)
如果结果表为空,则说明your_table_name
不存在。示例输出:PRAGMA schema.table_info(table-name);
此pragma针对命名表中的每个列返回一行。结果集中的列包括列名称、数据类型、该列是否可以为NULL以及该列的默认值。结果集中的“pk”列对于不是主键的列为零,对于是主键的列,则是主键中该列的索引。
在table_info pragma中命名的表也可以是视图。
cid|name|type|notnull|dflt_value|pk
0|id|INTEGER|0||1
1|json|JSON|0||0
2|name|TEXT|0||0
SQLite表名不区分大小写,但默认情况下比较是区分大小写的。为了使其在所有情况下正常工作,您需要添加COLLATE NOCASE
。
SELECT name FROM sqlite_master WHERE type='table' AND name='table_name' COLLATE NOCASE
如果您收到“表已经存在”错误,请按照以下方式更改SQL字符串:
CREATE table IF NOT EXISTS table_name (para1,para2);
通过这种方式,您可以避免异常情况。
如果你正在使用fmdb,我认为你可以只需导入FMDatabaseAdditions并使用布尔函数:
[yourfmdbDatabase tableExists: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 EXISTS(SELECT 1 FROM sqlite_master WHERE type="table" AND name="table_name");
似乎将结果缩减为布尔值结果(只能是0或1,没有其他值) - undefined