Bagaimana cara memeriksa di SQLite apakah ada tabel?

895

Bagaimana saya, andal , memeriksa dalam SQLite, apakah ada tabel pengguna tertentu?

Saya tidak meminta cara yang tidak dapat diandalkan seperti memeriksa apakah "pilih *" di atas meja mengembalikan kesalahan atau tidak (apakah ini ide yang bagus?).

Alasannya seperti ini:

Dalam program saya, saya perlu membuat dan mengisi beberapa tabel jika belum ada.

Jika sudah ada, saya perlu memperbarui beberapa tabel.

Haruskah saya mengambil jalan lain sebagai gantinya untuk memberi tanda bahwa tabel yang dimaksud telah dibuat - katakan misalnya, dengan membuat / meletakkan / mengatur bendera tertentu dalam file inisialisasi / pengaturan program saya pada disk atau sesuatu?

Atau apakah pendekatan saya masuk akal?

PoorLuzer
sumber
SQLite akan memunculkan eksepsi jika tabel di pilih tidak ada. Tidak perlu lagi ada pekerjaan mewah.
NoChance
34
@NoChance itu akan, tetapi begitu juga sejumlah hal lainnya. Itu agak seperti melihat apakah pohon itu benar-benar ada di sana dengan mengemudi ke depan dengan mata tertutup, Anda akan mengetahui satu dan lain cara :)
randomsock
@ Merkomsock, contoh yang bagus, tapi agak menakutkan, khususnya jika mobil itu adalah mobil saya ...
NoChance
@ Merkomsock, saya tidak tahu apa konvensi sqlite, tapi lebih pythonic untuk meminta maaf daripada izin. yaitu menangkap pengecualian daripada menggunakan kondisional.
Eric
1
@ Eric Sampai sekarang, pertanyaannya tidak melibatkan Python, tetapi dengan asumsi memang demikian, kesalahannya adalah generik sqlite3.OperationalError, jadi Anda harus menguraikan pesan kesalahan untuk memastikan itu misalnya pesan "tabel TABLE_NAME sudah ada" saat Anda membuat sebuah tabel, dan jika tidak, reraise kesalahan dan saya pikir tidak ada jaminan frase kesalahan tidak akan berubah.
Markus von Broady

Jawaban:

1023

Saya melewatkan entri FAQ itu.

Lagi pula, untuk referensi di masa mendatang, kueri lengkapnya adalah:

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

Di mana {table_name}nama tabel untuk diperiksa.

Bagian dokumentasi untuk referensi: Format File Database. 2.6. Penyimpanan Skema Database SQL

  • Ini akan mengembalikan daftar tabel dengan nama yang ditentukan; artinya, kursor akan memiliki hitungan 0 (tidak ada) atau hitungan 1 (memang ada)
PoorLuzer
sumber
7
Manakah dari dokumentasi SQLite yang mencakup tabel sistem ini?
Pawel Veselov
29
@ Pawel Veselov: Bagian berjudul "Format File Untuk Database SQLite": sqlite.org/fileformat2.html
Bryan Oakley
14
Ini tidak akan bekerja untuk tabel TEMP. Tabel TEMP berada di "sqlite_temp_master."
PatchyFog
11
Apakah ini mengembalikan boolean? Apa yang dikembalikan jika tabel ada atau tidak ada?
Dagrooms
8
@ Kamar ini akan mengembalikan daftar tabel dengan nama yang ditentukan; artinya, kursor akan memiliki hitungan 0 (tidak ada) atau hitungan 1 (memang ada).
Rein S
555

Jika Anda menggunakan SQLite versi 3.3+ Anda dapat dengan mudah membuat tabel dengan:

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

Dengan cara yang sama, Anda bisa menghapus tabel hanya jika ada dengan menggunakan:

drop table if exists TableName
arthur johnston
sumber
3
Perhatikan bahwa create tablepernyataan tidak lengkap (tidak ada spesifikasi kolom tabel).
Eric Platon
11
ada juga konstruksi yang serupa untuk indeks: buat indeks jika tidak ada TableName_col1 di TableName (col1)
lowtech
26
Ini seharusnya bukan jawaban yang diterima, tetapi akankah jika pertanyaan itu diucapkan secara berbeda. OP tidak bertanya bagaimana memeriksa tabel sebelum menjatuhkan atau membuat. Bagaimana jika Anda harus meminta tabel yang mungkin tidak ada? Ini adalah masalah yang saya hadapi sekarang, dan jawaban yang diterima bekerja paling baik dalam pernyataan masalah umum ini. Ini adalah alternatif cepat yang bagus.
Dagrooms
@ Kamar tidur, Anda mungkin benar. Meskipun OP tidak menanyakan hal ini, saya mencari jawaban ini :)
earik87
169

Variasi akan menggunakan SELECT COUNT (*) daripada SELECT NAME, yaitu

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

Ini akan mengembalikan 0, jika tabel tidak ada, 1 jika ada. Ini mungkin berguna dalam pemrograman Anda karena hasil numerik lebih cepat / mudah untuk diproses. Berikut ini menggambarkan bagaimana Anda akan melakukan ini di Android menggunakan SQLiteDatabase, Cursor, rawQuery dengan parameter.

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;
}
Stephen Quan
sumber
33
Saya percaya "SELECT 1" akan lebih cepat.
PatchyFog
Mengapa cursor.getInt (0) sama dengan jumlah catatan dalam basis data?
Semyon Danilov
1
Kami menghitung berapa kali TABEL muncul dalam skema sqlite. Hitungan 0 berarti tabel tidak ada. Hitungan 1 berarti tabel tersebut memang ada. Ini adalah hanya dua nilai penghitungan yang diharapkan.
Stephen Quan
1
Sementara angka (dari COUNT(*)) mudah diproses, lebih mudah untuk mengembalikan keberadaan baris atau tidak; jika ada baris di sana maka itu ada, jika tidak ada baris itu tidak ada. (Anda sudah memeriksa kegagalan dalam moveToFirst, sehingga pekerjaan akan dilakukan pada saat itu.)
dash-tom-bang
Perbarui kode Anda untuk menutup kursor sebelum Anda mengembalikan false.
Dave Thomas
43

Kamu bisa mencoba:

SELECT name FROM sqlite_master WHERE name='table_name'
Orang belanda
sumber
4
type = table akan berguna tho
mafu
Jika menggunakan C #, jangan gunakan perintah ini di a SQLiteReader reader = cmd.ExecuteReader();dan lakukan a dt.Load(reader)(di mana dta DataTable). Saya menemukan ini memberikan Object reference is not an instance of an objectpengecualian ini .Load()jika tabel tidak ditemukan. Sebaliknya, gunakan a SQLiteDataAdapter adapter = new SQLiteDataAdapter(cmd); dan lakukan adapter.Fill(ds), di mana dsa DataSet. Anda kemudian dapat melihat apakah ds.Tables.Count > 0dan return ds.Tables[0];jika demikian (atau else return null). Kemudian Anda dapat memeriksa bahwa DataTableuntuk menjadi null, jika dt.Rows != null, dan jikadt.Rows.Count>0
vapcguy
34

Menggunakan:

PRAGMA table_info(your_table_name)

Jika tabel yang dihasilkan kosong maka your_table_nametidak ada.

Dokumentasi:

PRAGMA schema.table_info (nama-tabel);

Pragma ini mengembalikan satu baris untuk setiap kolom dalam tabel bernama. Kolom dalam kumpulan hasil mencakup nama kolom, tipe data, apakah kolom tersebut NULL atau tidak, dan nilai default untuk kolom tersebut. Kolom "pk" di set hasil adalah nol untuk kolom yang bukan bagian dari kunci utama, dan merupakan indeks dari kolom di kunci utama untuk kolom yang merupakan bagian dari kunci utama.

Tabel yang disebutkan dalam pragma table_info juga bisa menjadi tampilan.

Contoh output:

cid|name|type|notnull|dflt_value|pk
0|id|INTEGER|0||1
1|json|JSON|0||0
2|name|TEXT|0||0
Diego Vélez
sumber
Ini adalah cara yang bagus untuk menentukan apakah ada tabel di Python.
Michael Murphy
atau Formulir Xamarin
SerenityNow
4
Ini adalah cara yang bagus untuk mendapatkan definisi kolom secara terprogram
w00t
33

Nama tabel SQLite peka huruf besar kecil, tetapi perbandingan huruf besar-kecil secara default. Agar ini berfungsi dengan baik dalam semua kasus, Anda perlu menambahkan COLLATE NOCASE.

SELECT name FROM sqlite_master WHERE type='table' AND name='table_name' COLLATE NOCASE
Brice M. Dempsey
sumber
33

Jika Anda mendapatkan kesalahan "tabel sudah ada", buat perubahan pada string SQL seperti di bawah ini:

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

Dengan cara ini Anda dapat menghindari pengecualian.

Rakesh Chaudhari
sumber
32

Lihat ini :

SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
Anton Gogolev
sumber
23

Jika Anda menggunakan fmdb , saya pikir Anda bisa mengimpor FMDatabaseAdditions dan menggunakan fungsi bool:

[yourfmdbDatabase tableExists:tableName].
pengguna655489
sumber
1
Pastikan Anda mengimpor "FMDatabaseAdditions.h" untuk menggunakan metode ini atau Anda akan bertanya-tanya mengapa mereka menghapusnya! :)
Will
Meskipun ini bisa menjadi jawaban yang benar, pertanyaannya adalah tentang sqlite bukan perpustakaan tertentu dalam bahasa tertentu. Saya pikir jawabannya harus menyediakan kode sql, bukan panggilan ke salah satu metode perpustakaan
nacho4d
13

Kode berikut mengembalikan 1 jika tabel ada atau 0 jika tabel tidak ada.

SELECT CASE WHEN tbl_name = "name" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "name" AND type = "table"
pacheco
sumber
1
Ini masih tidak akan mengembalikan apa pun jika tabel tidak ada, karena kondisi di mana mencegah hasil apa pun.
David Gausmann
10

Perhatikan bahwa untuk memeriksa apakah suatu tabel ada dalam basis data TEMP, Anda harus menggunakan sqlite_temp_masteralih-alih sqlite_master:

SELECT name FROM sqlite_temp_master WHERE type='table' AND name='table_name';
Scott Deerwester
sumber
9

Inilah fungsi yang saya gunakan:

Diberikan Objek SQLDatabase = db

public boolean exists(String table) {
    try {
         db.query("SELECT * FROM " + table);
         return true;
    } catch (SQLException e) {
         return false;
    }
}
DroidGrailer
sumber
1
Saya sedih harus menggunakan ini di aplikasi Android saya karena saya menemukan bahwa perangkat Samsung tidak menggunakan struktur tabel sqlite_master standar yang digunakan semua orang.
Anthony Chuinard
7

Gunakan kode ini:

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

Jika jumlah array yang dikembalikan sama dengan 1 artinya tabel ada. Kalau tidak, itu tidak ada.

asmad
sumber
4
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

Catatan: Ini berfungsi sekarang di Mac saya dengan Python 3.7.1

Douglas Goodall
sumber
Ini terlihat lebih bersih daripada semua jawaban lainnya .. Terima kasih !!
Harsha Vardhan
Tidak berfungsi untuk saya: harus menghapus tanda kurung {} di sekitar table_name, lalu boleh saja.
Banana
1
Pastikan table_nametidak disediakan dari sumber yang tidak dijelajahi (seperti input pengguna), jika tidak maka akan rentan terhadap injeksi SQL. Itu selalu lebih baik menggunakan parameter daripada teknik manipulasi teks
astef
3

Menggunakan

SELECT 1 FROM table LIMIT 1;

untuk mencegah semua catatan dibaca.

Franz Fahrenkrog Petermann
sumber
Ini mengembalikan NULL jika tabel ada tetapi tidak memiliki catatan.
radiospiel
Jika tabel tidak ada, itu akan menimbulkan kesalahan. Tangkap itu, dan Anda tahu itu tidak ada.
luckydonald
menggunakan penanganan kesalahan karena kontrol aliran umumnya tidak dianggap praktik terbaik. Ini mungkin harus dihindari.
Jeff Woodard
3

Anda bisa menulis kueri berikut untuk memeriksa keberadaan tabel.

SELECT name FROM sqlite_master WHERE name='table_name'

Di sini 'table_name' adalah nama tabel Anda apa yang Anda buat. Sebagai contoh

 CREATE TABLE IF NOT EXISTS country(country_id INTEGER PRIMARY KEY AUTOINCREMENT, country_code TEXT, country_name TEXT)"

dan cek

  SELECT name FROM sqlite_master WHERE name='country'
akn
sumber
6
Bagaimana ini berbeda dari jawaban yang dipilih paling banyak diterima dari 9 tahun yang lalu?
Kevin Van Dyck
3

Cara paling dapat diandalkan yang saya temukan di C # sekarang, menggunakan paket nuget sqlite-net-pcl terbaru (1.5.231) yang menggunakan SQLite 3, adalah sebagai berikut:

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

Menggunakan kueri SELECT sederhana - menurut saya - cukup dapat diandalkan. Sebagian besar dari semua itu dapat memeriksa keberadaan tabel di berbagai jenis database (SQLite / MySQL).

SELECT 1 FROM table;

Masuk akal ketika Anda dapat menggunakan mekanisme andal lainnya untuk menentukan apakah kueri berhasil (misalnya, Anda meminta basis data melalui QSqlQuery di Qt ).

Grz
sumber
1

fungsi c ++ memeriksa db dan semua database terlampir untuk keberadaan tabel dan kolom (opsional).

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

Sunting: Baru-baru ini menemukan fungsi sqlite3_table_column_metadata. Karenanya

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;}
NoComprende
sumber
public static boolean tableExists (database SQLiteDatabase, String tableName) {return database.rawQuery ("SELECT name FROM sqlite_master WHERE ketik = 'table' DAN nama = '" + tableName + "'", null) .moveToFirst (); }
nick
Cara yang sangat tidak efisien dan berisiko karena rangkaian string dapat berakhir dengan segalanya.
Andrea Moro
0

Ini adalah kode saya untuk 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");
    }
});

Dan yang lainnya:

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);
        });
    });
}
Zappescu
sumber
0

Saya pikir saya akan menempatkan 2 sen saya untuk diskusi ini, bahkan jika itu agak lama .. Kueri ini mengembalikan skalar 1 jika tabel ada dan 0 sebaliknya.

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

Tabel ada atau tidak dalam database dengan cepat

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)
    }
CSE 1994
sumber