Quelle est la différence entre les types de données SQLite connexes tels que INT, INTEGER, SMALLINT et TINYINT?


101

Lors de la création d'une table dans SQLite3, je suis confus face à tous les types de données possibles qui impliquent un contenu similaire, alors quelqu'un pourrait-il me dire la différence entre les types de données suivants?

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

Y a-t-il une documentation quelque part qui répertorie le min./max. capacités des différents types de données? Par exemple, je suppose que smallintdétient une valeur maximale plus grande que tinyint, mais une valeur plus petite que l'entier, mais je n'ai aucune idée de ce que sont ces capacités.

Réponses:


95

SQLite, techniquement, n'a pas de types de données, il y a des classes de stockage dans un système de typage manifeste, et oui, c'est déroutant si vous êtes habitué aux RDBMSes traditionnels . Tout, en interne, est stocké sous forme de texte. Les types de données sont forcés / convertis en divers emplacements de stockage en fonction des affinités (ala types de données attribués aux colonnes).

La meilleure chose que je vous recommande de faire est de:

  1. Oubliez temporairement tout ce que vous saviez sur les types de données de base de données autonomes

  2. Lisez le lien ci-dessus sur le SQLitesite.

  3. Prenez les types basés sur votre ancien schéma et voyez à quoi ils seraient mappés SQLite

  4. Migrez toutes les données vers la SQLitebase de données.

Remarque: Les limitations de type de données peuvent être lourdes, en particulier si vous ajoutez des durées, des dates ou des éléments de cette nature dans SQL. SQLitea très peu de fonctions intégrées pour ce genre de chose. Cependant, SQLitecela vous permet de créer facilement vos propres fonctions intégrées pour ajouter des durées de temps et des choses de cette nature, via la sqlite3_create_functionfonction de bibliothèque. Vous utiliseriez cette fonction à la place des procédures stockées traditionnelles.


1
Merci pour la réponse et le lien. Cela signifie-t-il que je devrais m'en tenir aux types de texte de base, numérique, entier, réel, aucun? Cela me semble très limité, surtout venant d'un fond MSSQL, Foxpro et Oracle. Cordialement.
Alan Harris-Reid

6
Je suis d'accord avec vous, cela semble limité au premier abord. Cependant, je pense que vous constaterez que SQLite est très indulgent dans la façon dont vous mettez des données dans la base de données via son système d'affinité. SQLite n'est pas autonome - il est conçu pour être un petit backend de base de données que vous placez dans de petites applications pour être accessible uniquement via une API d'accès à la base de données dans le code. Résoudre des problèmes dans SQLite est généralement une question de savoir comment ils veulent que vous le fassiez.
J. Polfer

Je m'en tiendrai aux types de base.
J. Polfer

4
@Alan: Vous trouverez peut-être utile de déclarer des colonnes d'affinité numérique comme DATEou BOOLEAN, mais je ne prendrais pas la peine de faire la distinction entre différentes tailles d'entiers. Cela est particulièrement vrai pour le cas de INTEGER PRIMARY KEY, le seul cas où le nom de type exact compte.
dan04

«Tout est stocké sous forme de texte» semble être faux selon sqlite.org/fileformat.html , qui dit que les nombres sont stockés sous forme de varints compacts / float64, et que seuls les objets blob et le texte sont stockés sous forme de chaînes
phiresky

47

La différence est le sucre syntaxique. Seules quelques sous-chaînes des noms de types importent en ce qui concerne l'affinité de type.

  • INT, INTEGER, SMALLINT, TINYINT → INTEGER affinité, car ils contiennent tous "INT".
  • Affinité LONGCHAR, LONGVARCHAR → TEXT, car ils contiennent "CHAR".
  • DEC, DECIMAL, DATETIME, SMALLDATETIME → NUMERIC, car ils ne contiennent aucune des sous-chaînes importantes.

Les règles de détermination de l'affinité sont répertoriées sur le site SQLite .

Si vous insistez sur un typage strict, vous pouvez l'implémenter avec des CHECKcontraintes:

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

Mais je ne m'en soucie jamais.

Quant à la capacité de chaque type:

  • INTEGERest toujours signé 64 bits. Notez que SQLite optimise le stockage des petits entiers en arrière-plan, donc TINYINT ne serait pas utile de toute façon.
  • REALest toujours 64 bits ( double).
  • TEXTet BLOBavoir une taille maximale déterminée par une macro de préprocesseur, qui est par défaut de 1 000 000 000 octets.

1
Joli tour. Notez que cette approche nécessite qu'une valeur à insérer / à mettre à jour ait la même classe de stockage que celle dans TYPEOF. Ainsi, les tentatives pour insérer un TEXTE qui serait autrement converti en classe de stockage NUMERIC / INTEGER par SQlite (c'est-à-dire, une telle conversion est sans perte selon sqlite.org/datatype3.html#affinity ) échoueraient. En d'autres termes, cette approche est plus stricte que l'approche ad hoc d'insertion de la valeur, puis de validation magique de la classe de stockage utilisée pour stocker cette valeur par SQLite. Pour une approche plus permissive, voir ma réponse ci-dessous.
eold

10

La plupart de ceux-ci sont là pour la compatibilité. Vous n'avez vraiment que des entiers, des flottants, du texte et des blob. Les dates peuvent être stockées sous forme de nombre (l'heure unix est un entier, l'heure Microsoft est un flottant) ou sous forme de texte.


Je l'ai utilisé pour des projets Web où tout a fini par être du texte mis dans une page html de toute façon. Je me suis dispensé de beaucoup de conversion de données et j'ai simplement utilisé du texte pour la plupart des colonnes. Cela a bien fonctionné.
Jay

3

NULL. La valeur est une valeur NULL.

INTEGER. La valeur est un entier signé, stocké sur 1, 2, 3, 4, 6 ou 8 octets en fonction de l'amplitude de la valeur.

REAL. La valeur est une valeur à virgule flottante, stockée sous forme de nombre à virgule flottante IEEE de 8 octets.

TEXT. La valeur est une chaîne de texte, stockée à l'aide du codage de la base de données (UTF-8, UTF-16BE ou UTF-16LE).

BLOB. La valeur est un blob de données, stocké exactement comme il a été entré.


1

En complément de la réponse de dan04, si vous souhaitez insérer aveuglément un NUMERICautre que zéro représenté par un TEXTmais assurez-vous que le texte est convertible en numérique:

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

Le cas d'utilisation typique est dans une requête d'un programme qui traite toutes les données comme du texte (pour l'uniformité et la simplicité, puisque SQLite le fait déjà). La bonne chose à ce sujet est que cela permet des constructions comme celle-ci:

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

ce qui est pratique dans le cas où vous utilisez des espaces réservés car vous n'avez pas à gérer spécialement ces champs numériques non nuls. Un exemple utilisant le sqlite3module de Python serait,

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

Dans l'exemple ci-dessus, toutes les valeurs de str_value_tupleseront échappées et placées entre guillemets sous forme de chaînes lorsqu'elles sont transmises à SQlite. Cependant, comme nous ne vérifions pas explicitement le type via TYPEOFmais uniquement la convertibilité en type , cela fonctionnera toujours comme vous le souhaitez (c'est-à-dire que SQLite le stockera sous forme numérique ou échouera dans le cas contraire).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.