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

Poo*_*zer 856 sqlite

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

我不是要求不可靠的方法,比如检查表上的"select*"是否返回错误(这是一个好主意吗?).

原因是这样的:

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

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

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

或者我的方法有意义吗?

Poo*_*zer 961

我错过了FAQ条目.

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

SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';
Run Code Online (Sandbox Code Playgroud)

{table_name}要检查的表的名称在哪里.

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

  • @Pawel Veselov:标题为"SQLite数据库的文件格式"的部分:http://www.sqlite.org/fileformat2.html (29认同)
  • 但是,这不适用于TEMP表.TEMP表位于"sqlite_temp_master"中. (13认同)
  • 这会返回一个布尔值吗?如果表格存在或不存在,它会返回什么? (11认同)
  • @Dagrooms这将返回一个指定名称的表列表; 也就是说,光标的计数为0(不存在)或计数为1(确实存在). (8认同)
  • 哪些SQLite文档涵盖了这些系统表? (7认同)
  • @PoorLuzer你可以更新你的答案如何检查查询结果以确定表是否存在?它将节省新手的时间 (5认同)
  • 从 SQLite 版本 3.33.0 开始,该表的新名称是“sqlite_schema”。旧名称仍然有效,但答案可能应该更新以提及新名称。 (3认同)

小智 532

如果您使用的是SQLite版本3.3+,则可以轻松创建一个表格:

create table if not exists TableName (col1 typ1, ..., colN typN)
Run Code Online (Sandbox Code Playgroud)

以同样的方式,您可以通过使用以下表来删除表:

drop table if exists TableName
Run Code Online (Sandbox Code Playgroud)

  • 这不应该是公认的答案,但如果问题措辞不同则会这样.在删除或创建之前,OP没有询问如何检查表.如果必须查询可能不存在的表,该怎么办?这是我现在面临的问题,并且接受的答案在这个一般问题陈述中效果最好.这是一个很好的快速替代方案. (24认同)
  • 索引也有类似的构造:**如果不存在则创建索引TableName上的TableName_col1(col1)** (10认同)
  • 请注意,`create table`语句不完整(缺少表列规范). (3认同)
  • @Dagrooms,你可能是对的。虽然OP没有问这个,但我一直在寻找这个答案:) (2认同)

Ste*_*uan 167

一种变化是使用SELECT COUNT(*)而不是SELECT NAME,即

SELECT count(*) FROM sqlite_master WHERE type='table' AND name='table_name';
Run Code Online (Sandbox Code Playgroud)

如果表不存在,则返回0,否则返回1.这可能对您的编程很有用,因为数字结果更快/更容易处理.下面说明如何使用SQLiteDatabase,Cursor,带参数的rawQuery在Android中执行此操作.

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我相信"SELECT 1"会更快. (31认同)
  • `SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type="table" AND name="table_name")` 似乎确实将结果缩减为布尔结果(0 或 1,没有其他) (6认同)
  • 我们正在计算 TABLE 在 sqlite 模式中出现的次数。计数为 0 表示该表不存在。计数为 1 表示该表确实存在。这是 count 仅有的两个期望值。 (3认同)

Gal*_*ian 41

你可以尝试:

SELECT name FROM sqlite_master WHERE name='table_name'
Run Code Online (Sandbox Code Playgroud)

  • type = table会很有用 (4认同)

Rak*_*ari 33

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

CREATE table IF NOT EXISTS table_name (para1,para2);
Run Code Online (Sandbox Code Playgroud)

这样就可以避免异常.


Bri*_*sey 32

SQLite表名称不区分大小写,但默认情况下比较区分大小写.要在所有情况下使其正常工作,您需要添加COLLATE NOCASE.

SELECT name FROM sqlite_master WHERE type='table' AND name='table_name' COLLATE NOCASE
Run Code Online (Sandbox Code Playgroud)


Die*_*lez 32

使用:

PRAGMA table_info(your_table_name)
Run Code Online (Sandbox Code Playgroud)

如果结果表为空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
Run Code Online (Sandbox Code Playgroud)

  • 这是以编程方式获取列定义的好方法 (4认同)

Ant*_*lev 31

看到这个:

SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
Run Code Online (Sandbox Code Playgroud)


use*_*489 22

如果你正在使用fmdb,我想你可以导入FMDatabaseAdditions并使用bool函数:

[yourfmdbDatabase tableExists:tableName].
Run Code Online (Sandbox Code Playgroud)


小智 13

如果表存在,则以下代码返回1;如果表不存在,则返回0.

SELECT CASE WHEN tbl_name = "name" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "name" AND type = "table"
Run Code Online (Sandbox Code Playgroud)

  • 如果表不存在,这仍然不会返回任何内容,因为 where 条件阻止任何结果。 (2认同)

Sco*_*ter 10

请注意,要检查TEMP数据库中是否存在表,必须使用sqlite_temp_master而不是sqlite_master:

SELECT name FROM sqlite_temp_master WHERE type='table' AND name='table_name';
Run Code Online (Sandbox Code Playgroud)


小智 9

这是我使用的功能:

给定一个SQLDatabase Object = db

public boolean exists(String table) {
    try {
         db.query("SELECT * FROM " + table);
         return true;
    } catch (SQLException e) {
         return false;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

使用此代码:

SELECT name FROM sqlite_master WHERE type='table' AND name='yourTableName';
Run Code Online (Sandbox Code Playgroud)

如果返回的数组计数等于1,则表示该表存在.否则它不存在.


AnK*_*nKr 6

您可以编写以下查询来检查表是否存在。

SELECT name FROM sqlite_master WHERE name='table_name'
Run Code Online (Sandbox Code Playgroud)

这里的“table_name”是您创建的表名称。例如

 CREATE TABLE IF NOT EXISTS country(country_id INTEGER PRIMARY KEY AUTOINCREMENT, country_code TEXT, country_name TEXT)"
Run Code Online (Sandbox Code Playgroud)

并检查

  SELECT name FROM sqlite_master WHERE name='country'
Run Code Online (Sandbox Code Playgroud)

  • 这与 9 年前已被接受的投票最高答案有何不同? (8认同)

Dou*_*all 6

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
Run Code Online (Sandbox Code Playgroud)

注意:这现在可以在我的 Mac 上使用 Python 3.7.1