INT, INTEGER, SMALLINT ve TINYINT gibi ilgili SQLite veri türleri arasındaki fark nedir?


101

SQLite3'te bir tablo oluştururken, benzer içerikleri ima eden tüm olası veri türleriyle karşılaştığımda kafam karışıyor, bu yüzden biri bana aşağıdaki veri türleri arasındaki farkı söyleyebilir mi?

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

Min./maks'ı listeleyen bazı belgeler var mı? çeşitli veri türlerinin kapasiteleri? Örneğin, tahminimden smallintdaha büyük bir maksimum değere sahip tinyint, ancak tamsayıdan daha küçük bir değere sahip, ancak bu kapasitelerin ne olduğu hakkında hiçbir fikrim yok.

Yanıtlar:


95

SQLite, teknik olarak, veri türü yoktur, açık bir yazma sisteminde depolama sınıfları vardır ve evet, geleneksel e- RDBMSpostalara alışkınsanız kafa karıştırıcıdır . Her şey dahili olarak metin olarak saklanır. Veri türleri, benzerliklere (sütunlara atanmış ala veri türleri) göre çeşitli depolama konumlarına zorlanır / dönüştürülür.

Yapmanızı tavsiye edeceğim en iyi şey şudur:

  1. Bağımsız veritabanı veri türleri hakkında bildiğiniz her şeyi geçici olarak unutun

  2. Siteden yukarıdaki bağlantıyı okuyun SQLite.

  3. Türleri eski şemanıza göre alın ve neyle eşleştiklerini görün SQLite

  4. Tüm verileri SQLiteveritabanına taşıyın .

Not: Veri türü sınırlamaları, özellikle içine zaman süreleri, tarihler veya bu türden şeyler eklerseniz kullanışsız olabilir SQL. SQLitebu tür şeyler için çok az yerleşik işlevi vardır. Bununla birlikte, kütüphane işlevi SQLitearacılığıyla zaman sürelerini ve bu nitelikteki şeyleri eklemek için kendi yerleşik işlevlerinizi oluşturmanın kolay bir yolunu sağlar sqlite3_create_function. Bu tesisi geleneksel saklanan prosedürler yerine kullanırsınız.


1
Cevap ve bağlantı için teşekkürler. Bu, temel metin türlerine (sayısal, tam sayı, gerçek, hiçbiri) bağlı kalmam gerektiği anlamına mı geliyor? Benim için çok sınırlı görünüyor, özellikle MSSQL, Foxpro ve Oracle geçmişinden geliyor. Saygılarımızla.
Alan Harris-Reid

6
Size katılıyorum, ilk başta sınırlı görünüyor. Bununla birlikte, SQLite'ın, afinite sistemi aracılığıyla veri tabanına nasıl veri koyduğunuz konusunda çok bağışlayıcı bulacağınızı düşünüyorum. SQLite bağımsız değildir - yalnızca koddaki bir veritabanı erişim API'si aracılığıyla erişilebilecek küçük uygulamalara yerleştirdiğiniz küçük bir veritabanı arka ucu olacak şekilde tasarlanmıştır. SQLite'da problem çözmek, genellikle bunu nasıl yapmanızı istediklerini anlamakla ilgilidir.
J. Polfer

Temel tiplere bağlı kalırım.
J. Polfer

4
@Alan: Sayısal yakınlık sütunlarını DATEveya olarak bildirmeyi yararlı bulabilirsiniz BOOLEAN, ancak farklı boyutlarda tamsayılar arasında ayrım yapmakla uğraşmam . Bu, özellikle INTEGER PRIMARY KEYtam tip adının önemli olduğu tek durum için geçerlidir.
dan04

Sayıların kompakt değişkenler / float64 olarak depolandığını ve yalnızca blob ve metnin dizeler olarak saklandığını söyleyen sqlite.org/fileformat.html'ye göre "Her şey metin olarak saklanıyor" yanlış görünüyor
phiresky

47

Aradaki fark sözdizimsel şekerdir. Tür yakınlığı söz konusu olduğunda, tür adlarının yalnızca birkaç alt dizesi önemlidir.

  • INT, INTEGER, SMALLINT, TINYINT → INTEGER yakınlık, çünkü hepsi "INT" içeriyor.
  • LONGCHAR, LONGVARCHAR → TEXT yakınlığı, çünkü "CHAR" içeriyorlar.
  • DECIMAL, DATETIME, SMALLDATETIME → NUMERIC, çünkü önemli olan alt dizelerin hiçbirini içermiyorlar.

Yakınlığı belirleme kuralları SQLite sitesinde listelenmiştir .

Sıkı yazmada ısrar ediyorsanız , bunu CHECKkısıtlamalarla uygulayabilirsiniz :

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

Ama onunla asla uğraşmam.

Her türün kapasitesine gelince:

  • INTEGERher zaman 64 bit olarak imzalanır. SQLite'in perde arkasındaki küçük tam sayıların depolanmasını optimize ettiğini unutmayın , bu nedenle TINYINT yine de yararlı olmayacaktır.
  • REALher zaman 64 bittir ( double).
  • TEXTve BLOBbir olması en büyük boyutu 1,000,000,000 bayta bir önişlemci makro belirlenir, varsayılan.

1
İyi numara. Bu yaklaşımın , içindeki ile aynı depolama sınıfına sahip olması için eklenecek / güncellenecek bir değer gerektirdiğini unutmayın TYPEOF. Bu nedenle, aksi takdirde SQlite tarafından NUMERIC / INTEGER depolama sınıfına dönüştürülecek olan bir METİN ekleme girişimleri (yani, bu tür dönüştürme sqlite.org/datatype3.html#affinity'ye göre kayıpsızdır ) başarısız olacaktır. Başka bir deyişle, bu yaklaşım, değeri girme ve ardından bu değeri SQLite tarafından saklamak için kullanılan depolama sınıfını bir şekilde sihirli bir şekilde doğrulamaya yönelik geçici yaklaşımdan daha katıdır . Daha hoşgörülü bir yaklaşım için aşağıdaki cevabıma bakın.
eold

10

Bunların çoğu uyumluluk için var. Gerçekten yalnızca tam sayı, kayan nokta, metin ve blobunuz var. Tarihler bir sayı (unix zamanı tam sayıdır, microsoft zamanı float) veya metin olarak saklanabilir.


Bunu web tabanlı projeler için kullandım, burada nihayetinde her şey zaten metin olarak bir html sayfasına yerleştirildi. Çok fazla veri dönüşümünden vazgeçtim ve sütunların çoğu için metin kullandım. İyi çalıştı.
Jay

3

NULL. Değer bir NULL değerdir.

INTEGER. Değer, değerin büyüklüğüne bağlı olarak 1, 2, 3, 4, 6 veya 8 baytta saklanan işaretli bir tamsayıdır.

REAL. Değer, 8 baytlık bir IEEE kayan nokta sayısı olarak saklanan bir kayan nokta değeridir.

TEXT. Değer, veritabanı kodlaması (UTF-8, UTF-16BE veya UTF-16LE) kullanılarak saklanan bir metin dizesidir.

BLOB. Değer, tam olarak girildiği gibi depolanan bir veri bloğudur.


1

Dan04 yanıtına bir ek olarak, bir ile NUMERICtemsil edilen sıfırdan başka bir körü körüne eklemek istiyorsanız, ancak metnin bir rakama dönüştürülebilirTEXT olduğundan emin olun :

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

Tipik kullanım durumu, tüm verileri metin olarak değerlendiren bir programdan gelen bir sorgudadır (SQLite zaten bunu yaptığı için tekdüzelik ve basitlik için). Bunun güzel yanı, bunun gibi yapılara izin vermesidir:

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

Bu, yer tutucular kullanmanız durumunda kullanışlıdır, çünkü bu tür sıfır olmayan sayısal alanları özel olarak işlemeniz gerekmez. Python'un sqlite3modülünü kullanan bir örnek ,

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

Yukarıdaki örnekte, str_value_tupleSQlite'a iletildiğinde içindeki tüm değerler atlanacak ve dizeler olarak alıntılanacaktır. Ancak, türü açıkça kontrol etmediğimizden, TYPEOFyalnızca türe dönüştürülebilirliği kontrol ettiğimizden , yine de istendiği gibi çalışacaktır (yani, SQLite bunu sayısal olarak saklayacak veya aksi takdirde başarısız olacaktır).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.