Как проверить в SQLite, существует ли таблица?

837

Как я могу надежно проверять SQLite, существует ли конкретная таблица пользователей?

Я не прошу о ненадежных способах проверки, если "select *" в таблице возвратил ошибку или нет (это даже хорошая идея?).

Причина такова:

В моей программе мне нужно создать, а затем заполнить некоторые таблицы, если они уже не существуют.

Если они уже существуют, мне нужно обновить некоторые таблицы.

Должен ли я взять какой-то другой путь вместо того, чтобы сигнализировать о том, что указанные таблицы уже созданы, например, путем создания/установки/установки определенного флага в файле инициализации/настройки программы на диске или что-то в этом роде?

Или мой подход имеет смысл?

  • 0
    SQLite сгенерирует исключение, если таблица в select не существует. Там просто нет необходимости в какой-либо более модной работе.
  • 21
    @ Скорее всего, так будет, но так же будет и с множеством других вещей. Это немного похоже на то, чтобы увидеть, действительно ли это дерево, двигаясь вперед с закрытыми глазами, вы узнаете так или иначе :)
Показать ещё 2 комментария
Теги:

20 ответов

946
Лучший ответ

Я пропустил этот FAQ.

В любом случае, для дальнейшего использования, полный запрос:

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

Где {table_name} - имя проверяемой таблицы.

Раздел документации для справки: Формат файла базы данных. 2.6. Хранение схемы базы данных SQL

  • 6
    Какая из документов SQLite охватывает эти системные таблицы?
  • 28
    @ Павел Веселов: Раздел под названием «Формат файла для баз данных SQLite»: sqlite.org/fileformat2.html
Показать ещё 9 комментариев
522

Если вы используете SQLite версии 3.3+, вы можете легко создать таблицу с помощью:

create table if not exists TableName (col1 typ1, ..., colN typN)

Таким же образом вы можете удалить таблицу только в том случае, если она существует с помощью:

drop table if exists TableName
  • 3
    Обратите внимание, что оператор create table является неполным (отсутствует спецификация столбцов таблицы).
  • 10
    Существует также аналогичная конструкция для индексов: создайте индекс, если он не существует. TableName_col1 для TableName (col1)
Показать ещё 1 комментарий
154

Вариантом будет использование 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;
}
  • 31
    Я считаю, что «ВЫБЕРИТЕ 1» будет еще быстрее.
  • 0
    Почему cursor.getInt (0) равно количеству записей в базе данных?
Показать ещё 4 комментария
38

Вы можете попробовать:

SELECT name FROM sqlite_master WHERE name='table_name'
  • 3
    Тип = таблица будет полезна, хотя
  • 0
    Если вы используете C #, не используйте эту команду в SQLiteReader reader = cmd.ExecuteReader(); и сделайте dt.Load(reader) (где dt - DataTable ). Я обнаружил, что эта Object reference is not an instance of an object исключения Object reference is not an instance of an object в .Load() если таблица не найдена. Вместо этого используйте SQLiteDataAdapter adapter = new SQLiteDataAdapter(cmd); и сделайте adapter.Fill(ds) , где ds - это DataSet . Затем вы можете увидеть, если ds.Tables.Count > 0 и return ds.Tables[0]; если это так (или else return null ). Затем вы можете проверить, что DataTable является null , если dt.Rows != null dt.Rows.Count>0 и если dt.Rows.Count>0
34

Если вы получаете ошибку "table already exists", внесите изменения в строку SQL, как показано ниже:

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

Таким образом вы можете избежать исключений.

30

Имена таблиц SQLite нечувствительны к регистру, но сравнение по умолчанию чувствительно к регистру. Чтобы сделать эту работу правильной во всех случаях, вам нужно добавить COLLATE NOCASE.

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

Использование:

PRAGMA table_info(your_table_name)

Если результирующая таблица пуста, то your_table_name не существует.

Документация:

PRAGMA schema.table_info (имя-таблицы);

Эта прагма возвращает одну строку для каждого столбца в названной таблице. Столбцы в результирующем наборе включают имя столбца, тип данных, может ли столбец NULL или значение по умолчанию для столбца. Столбец "pk" в результирующем наборе равен нулю для столбцов, которые не являются частью первичного ключа, и является индексом столбца в первичном ключе для столбцов, которые являются частью первичного ключа.

Таблица, названная в прайме table_info, также может быть представлением.

Пример вывода:

cid|name|type|notnull|dflt_value|pk
0|id|INTEGER|0||1
1|json|JSON|0||0
2|name|TEXT|0||0
  • 0
    Это отличный способ определить, существует ли таблица в Python.
  • 0
    или формы Xamarin
Показать ещё 1 комментарий
29

Смотрите this:

SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
22

Если вы используете fmdb, я думаю, что вы можете просто импортировать FMDatabaseAdditions и использовать функцию bool:

[yourfmdbDatabase tableExists:tableName].
  • 1
    Убедитесь, что вы импортировали «FMDatabaseAdditions.h», чтобы использовать этот метод, иначе вам будет интересно, почему они его удалили! :)
  • 0
    Хотя это может быть правильным ответом, вопрос был о sqlite, а не о конкретной библиотеке на определенном языке. Я думаю, что ответом должно быть предоставление кода SQL, а не вызов одного из методов библиотеки
13

Следующий код возвращает 1, если таблица существует или 0, если таблица не существует.

SELECT CASE WHEN tbl_name = "name" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "name" AND type = "table"
  • 1
    Это все равно ничего не вернет, если таблица не существует, потому что условие where предотвращает любой результат.
10

Обратите внимание, что для проверки наличия таблицы в базе данных TEMP вы должны использовать sqlite_temp_master вместо sqlite_master:

SELECT name FROM sqlite_temp_master WHERE type='table' AND name='table_name';
7

Здесь функция, которую я использовал:

С учетом объекта SQLDatabase Object = db

public boolean exists(String table) {
    try {
         db.query("SELECT * FROM " + table);
         return true;
    } catch (SQLException e) {
         return false;
    }
}
  • 1
    К сожалению, мне пришлось использовать это в моем приложении для Android, так как я обнаружил, что устройства Samsung не используют стандартную структуру таблиц sqlite_master, с которой все остальные работают.
6

Используйте этот код:

SELECT name FROM sqlite_master WHERE type='table' AND name='yourTableName';

Если количество возвращаемых массивов равно 1, это означает, что таблица существует. В противном случае он не существует.

3

Использование

SELECT 1 FROM table LIMIT 1;

чтобы предотвратить чтение всех записей.

  • 0
    Это возвращает NULL, если таблица существует, но не имеет никаких записей.
  • 0
    Если таблица не существует, она выдаст ошибку. Поймай это, и ты знаешь, что этого не существует.
Показать ещё 1 комментарий
1

Вы можете написать следующий запрос для проверки существования таблицы.

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'
  • 5
    Чем это отличается от уже принятого топ-9 ответа назад?
1

Использование простого запроса SELECT - на мой взгляд - вполне надежное. Больше всего он может проверить существование таблицы во многих разных типах баз данных (SQLite/MySQL).

SELECT 1 FROM table;

Имеет смысл, когда вы можете использовать другой надежный механизм для определения того, удалось ли выполнить запрос (например, вы запрашиваете базу данных через QSqlQuery в Qt).

0

Самый надежный способ, который я нашел в С# прямо сейчас, с использованием последнего пакета nuget sqlite-net-pcl (1.5.231), использующего SQLite 3, заключается в следующем:

var result = database.GetTableInfo(tableName);
        if ((result == null) || (result.Count == 0))
        {
            database.CreateTable<T>(CreateFlags.AllImplicit);
        }
0

Класс 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

Примечание: теперь это работает на моем Mac с Python 3.7.1

0

Я думал, что поставил бы свои 2 цента на эту дискуссию, даже если бы она была старой. Этот запрос возвращает скаляр 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
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);
        });
    });
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню