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

1106

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

我不是在询问像检查“select *”语句是否返回错误之类的不可靠方法(这是一个好主意吗?)。

原因如下:

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

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

是否应该采取其他方式来表示所涉及的表已经被创建 - 比如,在我的程序初始化/设置文件中创建/放置/设置某个标志或者类似操作?

还是我的方法有道理?


Ravens的评论 SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type="table" AND name="table_name");似乎将结果缩减为布尔值结果(只能是0或1,没有其他值) - undefined
31个回答

1
我倾向的方法是:
SELECT "name" FROM pragma_table_info("table_name") LIMIT 1;

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

0

如果你正在处理大数据表,我使用 Python 和 Sqlite 制作了一个简单的技巧,你可以用任何其他语言实现相似的想法。

步骤1:在创建表时不要使用(if not exists)命令。

如果你已经在之前创建过该表并且想再次创建它,运行此命令将会抛出异常,因此需要执行第二步。

步骤2:使用 tryexcept(或其他语言的 try 和 catch)来处理最后一个异常。

如果你之前没有创建过该表,try 代码块将继续执行,但如果你已经创建过该表,你可以在 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()

0

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

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

1
在返回前应该关闭resultSet - birgersp

0

在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)
    }

0

如果您正在使用Python文件并且显然使用sqlite3,请打开命令提示符或bash,无论您使用什么都可以使用

  1. python3 file_name.py 首先运行其中编写了SQL代码的文件。
  2. 然后运行sqlite3 file_name.db
  3. .table 这个命令将会给出表格(如果存在)。

0

我想在Diego Vélez的回答中补充关于PRAGMA语句的内容。

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

For example, information about the columns in an index can be read using the index_info pragma as follows:

PRAGMA index_info('idx52');

Or, the same content can be read using:

SELECT * FROM pragma_index_info('idx52');

The advantage of the table-valued function format is that the query can return just a subset of the PRAGMA columns, can include a WHERE clause, can use aggregate functions, and the table-valued function can be just one of several data sources in a join...

迭戈的回答提供了PRAGMA table_info(table_name)这样的选项,但这在其他查询中并没有太大用处。

因此,为了回答OP的问题并改进迭戈的答案,您可以执行以下操作

SELECT * FROM pragma_table_info('table_name');

或者更好的是,

SELECT name FROM pragma_table_list('table_name');

如果你想模仿PoorLuzers最受欢迎的答案。


0

这是我用于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);
        });
    });
}

0

这个 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;}

public static boolean tableExists(SQLiteDatabase database, String tableName){ return database.rawQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='" + tableName + "'", null).moveToFirst(); } - nick
非常低效和冒险的方式,因为字符串连接可能会导致一切。 - Andrea Moro

0
你可以使用一个简单的方法,我在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; }

}

0
根据以下查询可以确定表是否存在。
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。

为了解决这个问题,我看到有两个选择:

  1. 记住附加数据库的模式名称,并对其进行迭代
  2. 使用sqlite本地功能查找所有附加的数据库,并对此列表进行迭代

第二个选项可以通过使用以下方法来完成:

select * from pragma_database_list

这将返回订单、模式名称和数据库,然后您可以迭代所有{schema-name}.sqlite_master,并查找表是否存在以及在哪个模式中(可能存在多个)。参考:https://www.sqlite.org/dbpage.html#using_sqlite_dbpage_on_attach_ed_databases 是唯一的参考。我能找到关于此的信息,因此无法确定这是否是SQLite功能的一部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接