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

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

原因如下:

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

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

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

或者我的方法有意义吗?


当前回答

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

[yourfmdbDatabase tableExists:tableName].

其他回答

SQLite表名不区分大小写,但是默认情况下比较是区分大小写的。为了在所有情况下都能正常工作,需要添加COLLATE NOCASE。

SELECT name FROM sqlite_master WHERE type='table' AND name='table_name' COLLATE NOCASE

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

我喜欢的方法是:

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

如果您得到一个行结果,则该表存在。这是更好的(对我),然后检查sqlite_master,因为它也将检查附加和临时数据库。

一种变体是使用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;
}

我想我要对这个讨论发表我的意见,即使这是一个相当老的问题。 如果表存在,该查询返回标量1,否则返回0。

select 
    case when exists 
        (select 1 from sqlite_master WHERE type='table' and name = 'your_table') 
        then 1 
        else 0 
    end as TableExists