Qual è la differenza tra i tipi di dati SQLite correlati come INT, INTEGER, SMALLINT e TINYINT?


101

Quando creo una tabella in SQLite3, mi confondo di fronte a tutti i possibili tipi di dati che implicano contenuti simili, quindi qualcuno potrebbe dirmi la differenza tra i seguenti tipi di dati?

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

C'è della documentazione da qualche parte che elenca i file min./max. capacità dei vari tipi di dati? Ad esempio, immagino smallintcontenga un valore massimo maggiore di tinyint, ma un valore minore dell'intero, ma non ho idea di quali siano queste capacità.

Risposte:


95

SQLite, tecnicamente, non ha tipi di dati, ci sono classi di archiviazione in un sistema di tipizzazione manifest e sì, è fonte di confusione se sei abituato a RDBMSes. Tutto, internamente, viene memorizzato come testo. I tipi di dati vengono forzati / convertiti in varie posizioni di archiviazione in base alle affinità (ala tipi di dati assegnati alle colonne).

La cosa migliore che ti consiglierei di fare è:

  1. Dimentica temporaneamente tutto ciò che sapevi sui tipi di dati del database autonomo

  2. Leggi il link sopra dal SQLitesito.

  3. Prendi i tipi basati sul tuo vecchio schema e guarda a cosa si associano SQLite

  4. Migrare tutti i dati nel SQLitedatabase.

Nota: le limitazioni del tipo di dati possono essere macchinose, soprattutto se aggiungi durate temporali, date o cose del genere in SQL. SQLiteha pochissime funzioni integrate per questo genere di cose. Tuttavia, SQLitefornisce un modo semplice per creare le proprie funzioni integrate per aggiungere durate di tempo e cose di quella natura, attraverso la sqlite3_create_functionfunzione di libreria. Usereste quella struttura al posto delle tradizionali procedure memorizzate.


1
Grazie per la risposta e il link. Questo significa che dovrei attenermi ai tipi di testo di base, numerico, intero, reale, nessuno? Sembra molto limitato a me, soprattutto provenendo da un background MSSQL, Foxpro e Oracle. Saluti.
Alan Harris-Reid

6
Sono d'accordo con te, all'inizio sembra limitato. Tuttavia, penso che scoprirai che SQLite è molto indulgente nel modo in cui inserisci i dati nel database tramite il suo sistema di affinità. SQLite non è autonomo: è progettato per essere un piccolo backend di database che si inserisce in piccole applicazioni a cui si accede solo tramite un'API di accesso al database nel codice. Risolvere i problemi in SQLite è di solito una questione di capire come vogliono che tu lo faccia.
J. Polfer

Attaccherei ai tipi di base.
J. Polfer

4
@ Alan: potresti trovare utile dichiarare le colonne di affinità numerica come DATEo BOOLEAN, ma non mi preoccuperei di distinguere tra diverse dimensioni di numeri interi. Ciò è particolarmente vero per il caso di INTEGER PRIMARY KEY, l'unico caso in cui il nome del tipo esatto è importante.
dan04

"Tutto è archiviato come testo" sembra essere sbagliato secondo sqlite.org/fileformat.html , che dice che i numeri sono archiviati come varints / float64 compatti e solo il blob e il testo sono archiviati come stringhe
phiresky

47

La differenza è lo zucchero sintattico. Solo poche sottostringhe dei nomi di tipo sono importanti per quanto riguarda l'affinità di tipo.

  • INT, INTEGER, SMALLINT, TINYINT → INTEGER affinità, perché contengono tutti "INT".
  • LONGCHAR, LONGVARCHAR → Affinità TEXT, perché contengono "CHAR".
  • DEC, DECIMAL, DATETIME, SMALLDATETIME → NUMERIC, perché non contengono nessuna delle sottostringhe che contano.

Le regole per determinare l'affinità sono elencate nel sito SQLite .

Se insisti sulla digitazione rigorosa, puoi implementarla con CHECKvincoli:

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

Ma non me ne preoccupo mai.

Per quanto riguarda la capacità di ogni tipo:

  • INTEGERè sempre firmato a 64 bit. Nota che SQLite ottimizza l' archiviazione di piccoli numeri interi dietro le quinte, quindi TINYINT non sarebbe comunque utile.
  • REAL è sempre a 64 bit (double ).
  • TEXTe BLOBhanno una dimensione massima determinata da una macro del preprocessore, il cui valore predefinito è 1.000.000.000 di byte.

1
Bel trucco. Si noti che questo approccio richiede un valore da inserire / aggiornare per avere la stessa classe di archiviazione di quello in TYPEOF. Quindi, i tentativi di inserire un TESTO che altrimenti verrebbe convertito in una classe di archiviazione NUMERIC / INTEGER da SQlite (ovvero, tale conversione è senza perdite come per sqlite.org/datatype3.html#affinity ) fallirebbe. In altre parole, questo approccio è più rigoroso dell'approccio ad hoc di inserire il valore e quindi convalidare in qualche modo magicamente la classe di archiviazione utilizzata per archiviare quel valore da SQLite. Per un approccio più permissivo, vedi la mia risposta di seguito.
fino

10

La maggior parte di questi sono lì per compatibilità. Hai davvero solo numeri interi, float, text e blob. Le date possono essere memorizzate come numero (l'ora unix è intero, l'ora di microsoft è float) o come testo.


L'ho usato per progetti basati sul web in cui alla fine tutto è finito per essere testo inserito comunque in una pagina html. Ho rinunciato a molte conversioni di dati e ho usato solo testo per la maggior parte delle colonne. Ha funzionato bene.
Jay

3

NULL. Il valore è un valore NULL.

INTEGER. Il valore è un numero intero con segno, memorizzato in 1, 2, 3, 4, 6 o 8 byte a seconda della grandezza del valore.

REAL. Il valore è un valore in virgola mobile, memorizzato come numero in virgola mobile IEEE a 8 byte.

TEXT. Il valore è una stringa di testo, memorizzata utilizzando la codifica del database (UTF-8, UTF-16BE o UTF-16LE).

BLOB. Il valore è un blob di dati, archiviato esattamente come è stato immesso.


1

In aggiunta alla risposta da dan04, se vuoi inserire ciecamente un NUMERICdiverso da zero rappresentato da a TEXTma assicurati che il testo sia convertibile in un numerico:

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

Il caso d'uso tipico è in una query da un programma che tratta tutti i dati come testo (per uniformità e semplicità, poiché SQLite lo fa già). La cosa bella di questo è che consente costrutti come questo:

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

il che è comodo nel caso in cui si utilizzino segnaposto perché non è necessario gestire in modo speciale questi campi numerici diversi da zero. Un esempio che utilizza il sqlite3modulo di Python potrebbe essere,

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

Nell'esempio precedente, tutti i valori in str_value_tupleverranno sottoposti a escape e citati come stringhe quando vengono passati a SQlite. Tuttavia, poiché non stiamo controllando esplicitamente il tipo tramite TYPEOFma solo la convertibilità in tipo , funzionerà comunque come desiderato (cioè, SQLite lo memorizzerà come un numero o fallirà altrimenti).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.