2009-10-21 24 views
719

W jaki sposób, wiarygodnie, sprawdź w SQLite, czy istnieje konkretna tabela użytkownika?Jak sprawdzić w SQLite, czy tabela istnieje?

Nie proszę o nierzetelne sposoby sprawdzania, czy "wybierz *" na stole zwrócił błąd, czy nie (czy to nawet dobry pomysł?).

Powodem jest tak:

W moim programie, trzeba utworzyć, a następnie zapełnić kilka tabel, jeśli nie istnieje.

Jeśli już istnieją, muszę zaktualizować niektóre tabele.

Czy powinienem przyjąć inną ścieżkę, aby zasygnalizować, że tabele, o których mowa, zostały już utworzone - powiedzmy na przykład, tworząc/ustawiając/ustawiając pewną flagę w moim pliku inicjującym program/ustawienia na dysku lub coś podobnego?

Czy moje podejście ma sens?

+0

SQLite rzuci wyjątek, jeśli tabela w selekcji nie istnieje. Po prostu nie ma potrzeby wykonywania żadnych dodatkowych czynności. – NoChance

+8

@NoChance to będzie, ale tak samo jak wiele innych rzeczy. To trochę tak, jakby zobaczyć, czy to drzewo jest tam, jadąc naprzód z zamkniętymi oczami, dowiesz się w ten czy inny sposób :) – randomsock

+0

@randomsock, ładny przykład, ale trochę przerażający, szczególnie jeśli samochód był moim samochodem ... – NoChance

Odpowiedz

821

Tęskniłem że wpis FAQ.

W każdym razie, do wykorzystania w przyszłości, pełna zapytania to:

SELECT name FROM sqlite_master WHERE type='table' AND name='table_name'; 
+6

Która z dokumentacji SQLite dotyczy tych tabel systemowych? –

+28

@Pawel Veselov: Sekcja zatytułowana "Format plików dla baz danych SQLite": http://www.sqlite.org/fileformat2.html –

+1

To nie działa, jeśli używasz Adobe AIR SQLite, tutaj jest (lepsza) alternatywa dla przypadku, który programujesz w AS3/Air: http://stackoverflow.com/questions/4601707/air-and-sqlite-if-table-exists-conditional – CenterOrbit

23

Zobacz this:

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

można spróbować:

SELECT name FROM sqlite_master WHERE name='table_name' 
+3

type = tabela byłaby przydatna w przypadku – mafu

+0

Jeśli używasz C#, nie używaj tego polecenia w 'SQLiteReader reader = cmd.ExecuteReader();' i wykonaj 'dt.Load (reader)' (gdzie 'dt 'jest' DataTable'). Znalazłem, że daje to 'Odwołanie do obiektu nie jest instancją wyjątku obiektu' na .Load() 'jeśli tabela nie zostanie znaleziona. Zamiast tego użyj adaptera SQLiteDataAdapter = new SQLiteDataAdapter (cmd); 'i wykonaj' adapter.Fill (ds) ', gdzie' ds' to 'DataSet'. Możesz wtedy sprawdzić, czy 'ds.Tables.Count> 0' i' return ds.Tables [0]; 'if yes (lub' else return null'). Następnie możesz sprawdzić, czy 'DataTable' jest" null ", jeśli' dt.Rows! = Null', a jeśli 'dt.Rows.Count> 0' – vapcguy

467

Jeśli używasz wersji SQLite 3.3+ można łatwo utworzyć tabelę z:

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

W ten sam sposób można usunąć tabelę tylko wtedy, gdy istnieje: przy użyciu:

drop table if exists TableName 
+3

Należy zauważyć, że instrukcja "create table' jest niekompletna (brakuje specyfikacji kolumn tabeli). –

+9

istnieje również podobna konstrukcja dla indeksów: ** utwórz indeks, jeśli nie istnieje TableName_col1 na TableName (col1) ** – lowtech

+13

To nie powinna być akceptowana odpowiedź, ale gdyby pytanie było inaczej sformułowane. PO nie pytał, jak sprawdzić tabelę przed upuszczeniem lub utworzeniem. Co jeśli musisz zapytać o tabelę, która prawdopodobnie nie istnieje? Na tym właśnie polega problem, a zaakceptowana odpowiedź działa najlepiej w tym ogólnym stwierdzeniu problemu. To dobra, szybka alternatywa. – Dagrooms

12

Poniższy kod zwraca 1, jeśli tabela istnieje lub 0, jeśli tabela nie istnieje.

SELECT CASE WHEN tbl_name = "name" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "name" AND type = "table" 
145

Odmiana byłoby użyć SELECT COUNT (*) zamiast nazwy SELECT tj

SELECT count(*) FROM sqlite_master WHERE type='table' AND name='table_name'; 

powoduje przywrócenie 0, jeżeli tabela nie istnieje, a 1 jeżeli jest. Jest to prawdopodobnie przydatne w twoim programowaniu, ponieważ wynik liczbowy jest szybszy/łatwiejszy do przetworzenia. Poniższe ilustruje, w jaki sposób można to zrobić w systemie Android przy użyciu SQLiteDatabase, Cursor, rawQuery z parametrami.

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; 
} 
+25

Wierzę, że "SELECT 1" będzie jeszcze szybszy. – PatchyFog

+0

Dlaczego cursor.getInt (0) jest równy zliczaniu rekordów w bazie danych? –

+1

Liczymy ile razy TABELA pojawia się w schemacie sqlite. Liczba 0 oznacza, że ​​tabela nie istnieje. Liczba 1 oznacza, że ​​tabela istnieje. Są to jedyne dwie spodziewane wartości liczenia. –

21

Jeśli używasz fmdb, myślę, że można po prostu FMDatabaseAdditions import i użyć funkcji bool:

[yourfmdbDatabase tableExists:tableName]. 
+1

Upewnij się, że importujesz "FMDatabaseAdditions.h", aby użyć tej metody, inaczej będziesz się zastanawiać, dlaczego ją usunęli! :) – Will

+0

Chociaż może to być poprawna odpowiedź, pytanie dotyczyło sqlite, a nie konkretnej biblioteki w danym języku. Myślę, że odpowiedź powinna polegać na dostarczeniu kodu SQL, a nie na wywołaniu jednej z metod biblioteki – nacho4d

1

Stosując proste zapytanie SELECT jest - moim zdaniem - dość wiarygodne. Przede wszystkim może sprawdzić istnienie tabeli w wielu różnych typach baz danych (SQLite/MySQL).

SELECT 1 FROM table; 

To ma sens, gdy można użyć innego wiarygodnego mechanizmu ustalania jeśli zapytanie udało (na przykład, zapytań do bazy danych poprzez QSqlQuery w Qt).

6

Tutaj funkcja, że ​​stosuje się:

względu Object SQLDatabase = dB

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

Niestety musiałem użyć tego w mojej aplikacji na Androida, ponieważ odkryłem, że urządzenia Samsung nie używają standardowej struktury tabel sqlite_master, którą każdy jeszcze pracuje. –

6

Zastosowanie kod:

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

Jeśli zwrócona Ilość macierzy jest równy 1, to znaczy tabela istnieje. W przeciwnym razie nie istnieje.

22

W nazwach tabel SQLite nie jest rozróżniana wielkość liter, ale w porównaniu domyślnie rozróżniana jest wielkość liter. Aby to działało poprawnie we wszystkich przypadkach, musisz dodać COLLATE NOCASE.

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

Należy zauważyć, że w celu sprawdzenia, czy tabela istnieje w bazie danych TEMP, należy użyć sqlite_temp_master zamiast sqlite_master:

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

Zastosowanie:

PRAGMA table_info(your_table_name) 

Jeśli uzyskany stół jest pusty następnie your_table_name nie istnieje.

Dokumentacja:

PRAGMA schema.table_info (table-name);

Ta pragma zwraca jeden wiersz dla każdej kolumny w określonej tabeli. Kolumny w zestawie wyników zawierają nazwę kolumny, typ danych, niezależnie od tego, czy kolumna może mieć wartość NULL, czy domyślną wartość kolumny. Kolumna "pk" w zestawie wyników wynosi zero dla kolumn, które nie są częścią klucza podstawowego, i jest indeksem kolumny klucza głównego dla kolumn, które są częścią klucza podstawowego.

Tabela określona w pragma table_info może być również widokiem.

Przykâadowa:

cid|name|type|notnull|dflt_value|pk 
0|id|INTEGER|0||1 
1|json|JSON|0||0 
2|name|TEXT|0||0 
+0

To jest świetny sposób, aby ustalić, czy tabela istnieje w Pythonie. –

+0

lub Xamarin Forms – SerenityNow

+0

To jest świetny sposób, aby programowo uzyskać definicje kolumn – w00t

3

Zastosowanie

SELECT 1 FROM table LIMIT 1; 

aby zapobiec wszelkie rekordy od odczytania.

+0

Zwraca wartość NULL, jeśli tabela istnieje, ale nie ma żadnych rekordów. – radiospiel

+0

Jeśli tabela nie istnieje, spowoduje błąd. Złap to i wiesz, że to nie istnieje. – luckydonald

+0

przy użyciu obsługi błędów, ponieważ kontrola przepływu nie jest zazwyczaj uważana za najlepszą praktykę. Prawdopodobnie powinno się tego unikać. –

32

Jeśli otrzymujesz „tabela już istnieje” błąd, dokonać zmian w ciągu SQL jak poniżej:

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

W ten sposób można uniknąć wyjątki.

0

To jest mój kod 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"); 
    } 
}); 

a drugi:

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

Myślałam kładę moje 2 grosze do tej dyskusji, nawet jeśli jest to dość stary .. Ta kwerenda zwraca wartość skalarną 1, jeśli tabela istnieje i 0 w przeciwnym razie.

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