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

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

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

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

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

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

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

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

885 sqlite
21.10.2009 14:22:10
SQLite сгенерирует исключение, если таблица в select не существует. Там просто нет необходимости в более причудливой работе.
NoChance 3.10.2016 18:22:02
@ Скорее всего, так и будет, но будет и множество других вещей. Это немного похоже на то, чтобы увидеть, действительно ли это дерево, двигаясь вперёд с закрытыми глазами, вы узнаете так или иначе :)
randomsock 11.02.2017 20:01:59
@randomsock, хороший пример, но немного страшно, особенно, если машина была моей машиной ...
NoChance 12.02.2017 18:12:08
@randomsock, я не знаю, что такое соглашение по sqlite, но просить прощения более питонно, чем разрешение. т.е. ловить исключение вместо использования условного.
Eric 18.10.2018 15:42:49
@Eric На данный момент этот вопрос не касается Python, но при условии, что это так, ошибка является общей sqlite3.OperationalError, поэтому вам нужно проанализировать сообщение об ошибке, чтобы убедиться, что это, например, сообщение «таблица TABLE_NAME уже существует» при создании таблица, а если нет, то переформулируйте ошибку, и я думаю, что нет никакой гарантии, что формулировка ошибки не изменится.
Markus von Broady 17.09.2019 19:23:39
22 ОТВЕТА

Смотрите это :

SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
32
21.10.2009 14:25:32

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

SELECT name FROM sqlite_master WHERE name='table_name'
43
21.10.2009 14:25:51
type = table было бы полезно tho
mafu 30.03.2012 13:02:04
Если вы используете C #, не используйте эту команду в a SQLiteReader reader = cmd.ExecuteReader();и делайте a dt.Load(reader)(где dtis DataTable). Я обнаружил, что это дает 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
vapcguy 16.11.2016 22:58:22
РЕШЕНИЕ

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

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

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

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

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

  • Это вернет список таблиц с указанным именем; то есть курсор будет иметь счетчик 0 (не существует) или счетчик 1 (существует)
1009
7.10.2019 09:53:01
Какая из документов SQLite охватывает эти системные таблицы?
Pawel Veselov 3.01.2012 04:59:37
@ Павел Веселов: Раздел под названием «Формат файла для баз данных SQLite»: sqlite.org/fileformat2.html
Bryan Oakley 11.01.2012 16:34:31
Это не будет работать для таблиц TEMP, однако. Таблицы TEMP находятся в «sqlite_temp_master».
PatchyFog 18.12.2012 16:04:44
Это возвращает логическое значение? Что он возвращает, если таблица существует или не существует?
Dagrooms 15.06.2015 18:24:11
@Dagrooms Возвращает список таблиц с указанным именем; то есть курсор будет иметь счетчик 0 (не существует) или счетчик 1 (существует).
Rein S 1.12.2015 19:42:13

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

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

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

drop table if exists TableName
549
31.05.2013 02:50:56
Обратите внимание, что create tableоператор является неполным (отсутствует спецификация столбцов таблицы).
Eric Platon 31.05.2013 02:45:08
Существует также аналогичная конструкция для индексов: создать индекс, если не существует TableName_col1 для TableName (col1)
lowtech 2.12.2013 14:34:23
Это не должен быть принятый ответ, но был бы, если бы вопрос был сформулирован по-другому. ОП не спрашивал, как проверить таблицу перед тем, как уронить или создать. Что делать, если вам нужно запросить таблицу, которая, возможно, не существует? Это проблема, с которой я сталкиваюсь сейчас, и принятый ответ лучше всего работает в этой общей формулировке проблемы. Это хорошая быстрая альтернатива.
Dagrooms 16.06.2015 18:15:05

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

SELECT CASE WHEN tbl_name = "name" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "name" AND type = "table"
13
3.03.2017 16:59:00
Это все равно ничего не вернет, если таблица не существует, потому что условие where предотвращает любой результат.
David Gausmann 24.04.2018 17:47:50

Вариантом будет использование 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;
}
168
6.07.2017 00:32:56
Я верю, что «ВЫБЕРИТЕ 1» будет еще быстрее.
PatchyFog 18.12.2012 15:49:29
Почему cursor.getInt (0) равно количеству записей в базе данных?
Semyon Danilov 23.01.2014 18:57:07
Мы рассчитываем, сколько раз TABLE появляется в схеме sqlite. Число 0 означает, что таблица не существует. Число 1 означает, что таблица существует. Это единственные два ожидаемых значения количества.
Stephen Quan 23.01.2014 23:55:20
Хотя число (из COUNT(*)) легко обрабатывается, еще проще вернуть существование строки или нет; если там есть строка, то она существует, если нет строки, то ее нет. (Вы уже проверите на провал в moveToFirst, поэтому работа будет выполнена в этот момент.)
dash-tom-bang 26.07.2016 17:05:19
Пожалуйста, обновите ваш код, чтобы закрыть курсор, прежде чем вы вернете false.
Dave Thomas 6.09.2016 18:42:17

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

[yourfmdbDatabase tableExists:tableName].
23
26.10.2015 12:10:18
Убедитесь, что вы импортировали «FMDatabaseAdditions.h», чтобы использовать этот метод, иначе вам будет интересно, почему они его удалили! :)
Will 17.03.2015 16:34:59
Хотя это может быть правильным ответом, вопрос был о sqlite, а не о конкретной библиотеке на определенном языке. Я думаю, что ответом должно быть предоставление кода SQL, а не вызов одного из методов библиотеки
nacho4d 5.04.2016 01:39:24

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

SELECT 1 FROM table;

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

2
3.03.2017 17:00:32

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

Имеется объект SQLDatabase = db

public boolean exists(String table) {
    try {
         db.query("SELECT * FROM " + table);
         return true;
    } catch (SQLException e) {
         return false;
    }
}
9
11.06.2012 17:56:33
К сожалению, мне пришлось использовать это в моем приложении для Android, так как я обнаружил, что устройства Samsung не используют стандартную структуру таблицы sqlite_master, с которой все остальные работают.
Anthony Chuinard 14.06.2015 05:18:52

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

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

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

7
3.03.2017 17:01:38

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

SELECT name FROM sqlite_master WHERE type='table' AND name='table_name' COLLATE NOCASE
33
22.02.2014 18:07:00

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

SELECT name FROM sqlite_temp_master WHERE type='table' AND name='table_name';
10
24.04.2014 15:49:33

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

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
33
1.11.2017 15:50:16
Это отличный способ определить, существует ли таблица в Python.
Michael Murphy 9.12.2014 07:01:17
или формы Xamarin
SerenityNow 16.08.2017 20:17:05
Это отличный способ получить определения столбцов программно
w00t 1.11.2017 15:47:44

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

SELECT 1 FROM table LIMIT 1;

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

3
28.10.2014 17:27:34
Это возвращает NULL, если таблица существует, но не имеет никаких записей.
radiospiel 14.01.2015 12:38:21
Если таблица не существует, она выдаст ошибку. Поймай это, и ты знаешь, что этого не существует.
luckydonald 1.07.2015 17:15:51
использование обработки ошибок в качестве управления потоком обычно не считается наилучшей практикой. Этого, вероятно, следует избегать.
Jeff Woodard 3.10.2016 20:56:42

Если вы получаете сообщение об ошибке «таблица уже существует», внесите изменения в строку SQL, как показано ниже:

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

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

33
3.03.2017 17:05:47

Это мой код для 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
3.03.2017 17:07:36

Я думал, что я бы положил 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
10.06.2017 22:13:28

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

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'
3
2.08.2018 10:14:55
Чем это отличается от уже принятого топ-9 ответа назад?
Kevin Van Dyck 2.08.2018 10:21:48
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

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

4
1.06.2019 07:54:40
Это выглядит чище, чем все остальные ответы .. Спасибо!
Harsha Vardhan 4.07.2019 15:53:48
Не работает для меня: нужно удалить квадратные скобки {} вокруг table_name, тогда это нормально.
Banana 4.08.2019 12:09:25
Убедитесь, что table_nameон не предоставлен из ненадежного источника (например, пользовательского ввода), иначе он будет уязвим для внедрения SQL. Всегда лучше использовать параметры вместо методов обработки текста
astef 27.08.2019 16:59:55

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

var result = database.GetTableInfo(tableName);
if ((result == null) || (result.Count == 0))
{
    database.CreateTable<T>(CreateFlags.AllImplicit);
}
3
1.06.2019 07:54:18

Таблица существует или нет в базе данных в 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
1.06.2019 07:51:40

Функция 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;}
2
20.01.2020 07:22:25
public static логическое tableExists (база данных SQLiteDatabase, String tableName) {return database.rawQuery ("ВЫБЕРИТЕ имя ИЗ sqlite_master WHERE type = 'table' AND name = '" + tableName + "'", null) .moveToFirst (); }
nick 16.11.2019 21:11:00