Jaka jest różnica między pokrewnymi typami danych SQLite, takimi jak INT, INTEGER, SMALLINT i TINYINT?


101

Tworząc tabelę w SQLite3, jestem zdezorientowany, gdy mam do czynienia ze wszystkimi możliwymi typami danych, które implikują podobną zawartość, więc czy ktoś mógłby mi powiedzieć, jaka jest różnica między następującymi typami danych?

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

Czy jest gdzieś dokumentacja, która wymienia min./maks. możliwości różnych typów danych? Na przykład, wydaje mi się, że smallintzawiera większą wartość maksymalną niż tinyint, ale mniejszą wartość niż liczba całkowita, ale nie mam pojęcia, jakie są te pojemności.

Odpowiedzi:


95

SQLitetechnicznie rzecz biorąc, nie ma typów danych, istnieją klasy pamięci w manifestowym systemie pisania i tak, jest to mylące, jeśli jesteś przyzwyczajony do tradycyjnych RDBMSes. Wszystko wewnętrznie jest przechowywane jako tekst. Typy danych są wymuszane / konwertowane na różne lokalizacje pamięci w oparciu o koligacje (ala typy danych przypisane do kolumn).

Najlepsze, co poleciłbym, to:

  1. Tymczasowo zapomnij o wszystkim, co wiedziałeś o typach danych autonomicznej bazy danych

  2. Przeczytaj powyższy link ze SQLitestrony.

  3. Weź typy oparte na starym schemacie i zobacz, do czego będą mapowane SQLite

  4. Przeprowadź migrację wszystkich danych do SQLitebazy danych.

Uwaga: Ograniczenia typu danych mogą być uciążliwe, zwłaszcza jeśli dodasz czasy trwania, daty lub rzeczy tego rodzaju w SQL. SQLitema bardzo mało wbudowanych funkcji do tego typu rzeczy. Jednak SQLitezapewnia łatwy sposób tworzenia własnych wbudowanych funkcji w celu dodawania czasów trwania i rzeczy tego rodzaju za pomocą sqlite3_create_functionfunkcji biblioteki. Używałbyś tego narzędzia zamiast tradycyjnych procedur składowanych.


1
Dzięki za odpowiedź i link. Czy to oznacza, że ​​powinienem trzymać się podstawowych typów tekstu, liczbowych, całkowitych, rzeczywistych, żadnych? Wydaje mi się to bardzo ograniczone, szczególnie w kontekście MSSQL, Foxpro i Oracle. Pozdrowienia.
Alan Harris-Reid

6
Zgadzam się z tobą, na początku wydaje się to ograniczone. Myślę jednak, że przekonasz się, że SQLite jest bardzo wyrozumiały w sposobie, w jaki umieszczasz dane w bazie danych za pośrednictwem systemu powinowactwa. SQLite nie jest samodzielny - został zaprojektowany jako mały backend bazy danych, który umieszczasz w małych aplikacjach, aby uzyskać dostęp tylko za pośrednictwem interfejsu API dostępu do bazy danych w kodzie. Rozwiązywanie problemów w SQLite jest zwykle kwestią ustalenia, w jaki sposób chcą, abyś to zrobił.
J. Polfer

Trzymałbym się podstawowych typów.
J. Polfer

4
@Alan: Może się przydać zadeklarowanie kolumn podobieństwa liczbowego jako DATElub BOOLEAN, ale nie zawracałbym sobie głowy rozróżnianiem różnych rozmiarów liczb całkowitych. Jest to szczególnie prawdziwe w przypadku INTEGER PRIMARY KEY, jedynego przypadku, w którym ważna jest dokładna nazwa typu.
dan04

„Wszystko jest przechowywane jako tekst” wydaje się być błędne zgodnie z sqlite.org/fileformat.html , który mówi, że liczby są przechowywane jako compact varints / float64, a tylko blob i tekst są przechowywane jako ciągi
phiresky

47

Różnica polega na cukrze syntaktycznym. Tylko kilka podciągów nazw typów ma znaczenie, jeśli chodzi o powinowactwo do typów.

  • INT, INTEGER, SMALLINT, TINYINT → INTEGER powinowactwo, ponieważ wszystkie zawierają „INT”.
  • LONGCHAR, LONGVARCHAR → TEXT powinowactwo, ponieważ zawierają „CHAR”.
  • DEC, DECIMAL, DATETIME, SMALLDATETIME → NUMERIC, ponieważ nie zawierają żadnego z podciągów, które mają znaczenie.

Reguły określania powinowactwa są wymienione w witrynie SQLite .

Jeśli nalegasz na ścisłe pisanie, możesz zaimplementować to z CHECKograniczeniami:

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

Ale nigdy się tym nie przejmuję.

Jeśli chodzi o pojemność każdego typu:

  • INTEGERjest zawsze podpisany jako 64-bitowy. Zauważ, że SQLite optymalizuje przechowywanie małych liczb całkowitych za kulisami, więc TINYINT i tak nie byłby przydatny.
  • REALjest zawsze 64-bitowa ( double).
  • TEXTi BLOBmają maksymalny rozmiar określony przez makro preprocesora, który domyślnie wynosi 1 000 000 000 bajtów.

1
Niezła sztuczka. Zwróć uwagę, że to podejście wymaga, aby wartość do wstawienia / zaktualizowania miała taką samą klasę pamięci jak w TYPEOF. Tak więc próby wstawienia TEKSTU, który w przeciwnym razie zostałby przekonwertowany na klasę pamięci NUMERIC / INTEGER przez SQlite (tj. Taka konwersja jest bezstratna, jak na sqlite.org/datatype3.html#affinity ) zakończy się niepowodzeniem. Innymi słowy, to podejście jest bardziej rygorystyczne niż podejście ad-hoc polegające na wstawianiu wartości, a następnie magicznym sprawdzaniu klasy pamięci używanej do przechowywania tej wartości przez SQLite. Aby uzyskać bardziej liberalne podejście, zobacz moją odpowiedź poniżej.
eold

10

Większość z nich jest dostępna dla kompatybilności. Tak naprawdę masz tylko liczby całkowite, zmiennoprzecinkowe, tekstowe i obiekty blob. Daty mogą być przechowywane jako liczby (czas unix to liczba całkowita, czas Microsoft to liczba zmiennoprzecinkowa) lub tekst.


Używałem go w projektach internetowych, gdzie ostatecznie wszystko i tak skończyło się tekstem umieszczonym na stronie html. Zrezygnowałem z dużej konwersji danych i po prostu użyłem tekstu w większości kolumn. Udało się dobrze.
Jay

3

NULL. Wartość jest wartością NULL.

INTEGER. Wartość jest liczbą całkowitą ze znakiem, przechowywaną w 1, 2, 3, 4, 6 lub 8 bajtów, w zależności od wielkości wartości.

REAL. Wartość jest wartością zmiennoprzecinkową, przechowywaną jako 8-bajtowa liczba zmiennoprzecinkowa IEEE.

TEXT. Wartość jest ciągiem tekstowym przechowywanym przy użyciu kodowania bazy danych (UTF-8, UTF-16BE lub UTF-16LE).

BLOB. Wartość to zbiór danych przechowywanych dokładnie tak, jak zostały wprowadzone.


1

Jako dodatek do odpowiedzi z dan04, jeśli chcesz na ślepo wstawić NUMERICinne niż zero reprezentowane przez a, TEXTale upewnij się, że tekst można zamienić na numeryczny:

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

Typowy przypadek użycia to zapytanie z programu, który traktuje wszystkie dane jako tekst (dla jednolitości i prostoty, ponieważ SQLite już to robi). Zaletą tego jest to, że zezwala na takie konstrukcje:

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

co jest wygodne, jeśli używasz symboli zastępczych, ponieważ nie musisz specjalnie obsługiwać takich niezerowych pól numerycznych. Przykładem użycia sqlite3modułu Pythona byłoby:

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

W powyższym przykładzie wszystkie wartości w str_value_tuplezostaną zapisane w postaci znaków ucieczki i cytowane jako ciągi po przekazaniu do SQlite. Ponieważ jednak nie sprawdzamy jawnie typu via, TYPEOFa jedynie konwertowalność na typ , będzie on nadal działał zgodnie z oczekiwaniami (tj. SQLite albo zapisze go jako numeryczny, albo w przeciwnym razie zakończy się niepowodzeniem).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.