Apa perbedaan antara tipe data SQLite terkait seperti INT, INTEGER, SMALLINT, dan TINYINT?

101

Saat membuat tabel di SQLite3, saya bingung saat dihadapkan dengan semua kemungkinan tipe data yang menyiratkan konten serupa, jadi adakah yang bisa memberi tahu saya perbedaan antara tipe data berikut?

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

Apakah ada beberapa dokumentasi di suatu tempat yang mencantumkan min./max. kapasitas dari berbagai tipe data? Misalnya, saya kira smallintmemiliki nilai maksimum yang lebih besar dari tinyint, tetapi nilai yang lebih kecil dari bilangan bulat, tetapi saya tidak tahu apa kapasitas ini.

Alan Harris-Reid
sumber

Jawaban:

95

SQLite, secara teknis, tidak memiliki tipe data, ada kelas penyimpanan dalam sistem pengetikan manifes, dan ya, ini membingungkan jika Anda terbiasa dengan RDBMSes tradisional . Semuanya, secara internal, disimpan sebagai teks. Tipe data dipaksa / diubah menjadi berbagai lokasi penyimpanan berdasarkan afinitas (tipe data ala ditugaskan ke kolom).

Hal terbaik yang saya sarankan untuk Anda lakukan adalah:

  1. Lupakan untuk sementara semua yang biasa Anda ketahui tentang tipe data database mandiri

  2. Baca tautan di atas dari SQLitesitus.

  3. Pilih jenis berdasarkan skema lama Anda, dan lihat apa yang akan mereka petakan SQLite

  4. Migrasikan semua data ke SQLitedatabase.

Catatan: Batasan tipe data bisa merepotkan, terutama jika Anda menambahkan durasi waktu, atau tanggal, atau hal-hal semacam itu di SQL. SQLitememiliki sangat sedikit fungsi bawaan untuk hal semacam itu. Namun, SQLitemenyediakan cara mudah bagi Anda untuk membuat fungsi bawaan Anda sendiri untuk menambahkan durasi waktu dan hal-hal semacam itu, melalui sqlite3_create_functionfungsi perpustakaan. Anda akan menggunakan fasilitas itu sebagai pengganti prosedur tersimpan tradisional.

J. Polfer
sumber
1
Terima kasih atas balasan dan tautannya. Apakah ini berarti saya harus tetap menggunakan tipe dasar teks, numerik, integer, real, none? Sepertinya sangat terbatas untuk saya, terutama yang berasal dari latar belakang MSSQL, Foxpro dan Oracle. Salam.
Alan Harris-Reid
6
Saya setuju dengan Anda, tampaknya terbatas pada awalnya. Namun, saya pikir Anda akan menemukan bahwa SQLite sangat pemaaf dalam cara Anda memasukkan data ke dalam database melalui sistem afinitasnya. SQLite tidak berdiri sendiri - ini dirancang untuk menjadi backend database kecil yang Anda tempatkan di aplikasi kecil untuk diakses hanya melalui API akses database dalam kode. Memecahkan masalah di SQLite biasanya adalah masalah mencari tahu bagaimana mereka ingin Anda melakukannya.
J. Polfer
Saya akan tetap berpegang pada tipe dasar.
J. Polfer
4
@Alan: Anda mungkin merasa berguna untuk mendeklarasikan kolom afinitas numerik sebagai DATEatau BOOLEAN, tetapi saya tidak akan repot-repot membedakan berbagai ukuran bilangan bulat. Hal ini terutama berlaku untuk kasus INTEGER PRIMARY KEY, satu kasus di mana nama tipe yang tepat penting.
dan04
"Semuanya disimpan sebagai teks" tampaknya salah menurut sqlite.org/fileformat.html , yang mengatakan angka disimpan sebagai varints / float64 kompak, dan hanya blob dan teks yang disimpan sebagai string
phiresky
47

Perbedaannya adalah gula sintaksis. Hanya beberapa substring dari nama tipe yang penting sebagai afinitas tipe yang bersangkutan.

  • INT, INTEGER, SMALLINT, TINYINT → INTEGER afinitas, karena semuanya mengandung "INT".
  • LONGCHAR, LONGVARCHAR → afinitas TEXT, karena mengandung "CHAR".
  • DEC, DECIMAL, DATETIME, SMALLDATETIME → NUMERIC, karena tidak mengandung substring yang penting.

Aturan untuk menentukan afinitas dicantumkan di situs SQLite .

Jika Anda bersikeras pada pengetikan yang ketat, Anda dapat menerapkannya dengan CHECKbatasan:

CREATE TABLE T (
   N   INTEGER CHECK(TYPEOF(N) = 'integer'),
   Str TEXT CHECK(TYPEOF(Str) = 'text'),
   Dt  DATETIME CHECK(JULIANDAY(Dt) IS NOT NULL)
);

Tapi saya tidak pernah peduli dengan itu.

Adapun kapasitas masing-masing type:

  • INTEGERselalu ditandatangani 64-bit. Perhatikan bahwa SQLite mengoptimalkan penyimpanan bilangan bulat kecil di belakang layar, jadi TINYINT tidak akan berguna.
  • REALselalu 64-bit ( double).
  • TEXTdan BLOBmemiliki ukuran maksimum yang ditentukan oleh makro praprosesor, yang defaultnya adalah 1.000.000.000 byte.
dan04
sumber
1
Trik yang bagus. Perhatikan bahwa pendekatan ini memerlukan nilai-untuk-dimasukkan / diperbarui untuk memiliki kelas penyimpanan yang sama dengan yang ada di TYPEOF. Jadi, upaya untuk memasukkan TEXT yang sebaliknya akan dikonversi ke kelas penyimpanan NUMERIC / INTEGER oleh SQlite (yaitu, konversi seperti itu tanpa kerugian seperti per sqlite.org/datatype3.html#affinity ) akan gagal. Dengan kata lain, pendekatan ini lebih ketat daripada pendekatan ad-hoc dalam memasukkan nilai dan kemudian secara ajaib memvalidasi kelas penyimpanan yang digunakan untuk menyimpan nilai tersebut oleh SQLite. Untuk pendekatan yang lebih permisif, lihat jawaban saya di bawah ini.
eold
10

Sebagian besar ada untuk kompatibilitas. Anda benar-benar hanya memiliki integer, float, teks, dan blob. Tanggal dapat disimpan sebagai angka (waktu unix adalah integer, waktu microsoft adalah float) atau sebagai teks.

Jay
sumber
Saya telah menggunakannya untuk proyek berbasis web di mana pada akhirnya semuanya berakhir dengan teks yang dimasukkan ke dalam halaman html. Saya membuang banyak konversi data dan hanya menggunakan teks untuk sebagian besar kolom. Itu berhasil dengan baik.
Jay
3

NULL. Nilainya adalah nilai NULL.

INTEGER. Nilainya adalah bilangan bulat bertanda, disimpan dalam 1, 2, 3, 4, 6, atau 8 byte tergantung pada besarnya nilai.

REAL. Nilainya adalah nilai floating point, disimpan sebagai angka floating point IEEE 8-byte.

TEXT. Nilainya adalah string teks, disimpan menggunakan encoding database (UTF-8, UTF-16BE atau UTF-16LE).

BLOB. Nilai adalah sekumpulan data, disimpan persis seperti saat dimasukkan.

pengguna2393484
sumber
1

Sebagai tambahan untuk jawaban dari dan04, jika Anda ingin memasukkan secara membabi buta NUMERICselain nol yang diwakili oleh a TEXTtetapi pastikan teks tersebut dapat diubah menjadi numerik:

your_numeric_col NUMERIC CHECK(abs(your_numeric_col) <> 0)

Kasus penggunaan umum ada dalam kueri dari program yang memperlakukan semua data sebagai teks (untuk keseragaman & kesederhanaan, karena SQLite sudah melakukannya). Hal yang menyenangkan tentang ini adalah memungkinkan konstruksi seperti ini:

INSERT INTO table (..., your_numeric_column, ...) VALUES (..., some_string, ...)

yang nyaman jika Anda menggunakan placeholder karena Anda tidak harus menangani bidang numerik bukan nol secara khusus. Contoh menggunakan sqlite3modul Python adalah ,

conn_or_cursor.execute(
    "INSERT INTO table VALUES (" + ",".join("?" * num_values) + ")",   
    str_value_tuple)  # no need to convert some from str to int/float

Dalam contoh di atas, semua nilai di str_value_tupleakan di -escape dan dikutip sebagai string saat diteruskan ke SQlite. Namun, karena kami tidak memeriksa secara eksplisit tipe melalui TYPEOFtetapi hanya konvertibilitas ke tipe , ini akan tetap berfungsi seperti yang diinginkan (yaitu, SQLite akan menyimpannya sebagai numerik atau gagal jika tidak).

eold
sumber