В чем разница между связанными типами данных SQLite, такими как INT, INTEGER, SMALLINT и TINYINT?

При создании таблицы в SQLite3 я запутываюсь, когда сталкиваюсь со всеми возможными типами данных, которые подразумевают сходное содержимое, поэтому может ли кто-нибудь сказать мне разницу между следующими типами данных?

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

Есть ли какая-то документация где-то, где перечисляется min./max. емкости различных типов данных? Например, я полагаю, что smallint имеет большее максимальное значение, чем tinyint, но меньшее значение, чем целое число, но я не знаю, что это за возможности.

Ответ 1

SQLite, технически, не имеет типов данных, есть классы хранения в системе набора символов, и да, это сбивает с толку, если вы 'используется для традиционных RDBMS es. Все, внутренне, хранится как текст. Типы данных принудительно/конвертируются в различные места хранения на основе аффинностей (типы данных ala, назначенные столбцам).

Лучшее, что я рекомендую вам сделать, это:

  • Временно забыть все, что вы знали о автономных типах данных базы данных

  • Прочитайте приведенную выше ссылку с сайта SQLite.

  • Возьмите типы, основанные на старой схеме, и посмотрите, на что они будут сопоставляться в SQLite

  • Перенесите все данные в базу данных SQLite.

Примечание. Ограничения типа данных могут быть громоздкими, особенно если вы добавляете длительность времени или даты или такие вещи в SQL. SQLite имеет очень мало встроенных функций для такого рода вещей. Тем не менее, SQLite предоставляет вам простой способ сделать ваши собственные встроенные функции для добавления продолжительности времени и вещей такого характера через sqlite3_create_function функция библиотеки. Вы использовали бы это средство вместо традиционных хранимых процедур.

Ответ 2

Разница заключается в синтаксическом сахаре. Только несколько подстрок имен типов имеют значение как сродство типа.

  • INT, INTEGER, SMALLINT, TINYINT → INTEGER, потому что все они содержат "INT".
  • LONGCHAR, LONGVARCHAR → TEXT, потому что они содержат "CHAR".
  • DEC, DECIMAL, DATETIME, SMALLDATETIME → NUMERIC, потому что они не содержат никаких подстрок, которые имеют значение.

Правила определения сродства перечислены на сайте SQLite.

Если вы настаиваете на строгом вводе текста, вы можете реализовать его с ограничениями CHECK:

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

Но я никогда не беспокоюсь об этом.

Что касается емкости каждого типа:

  • INTEGER всегда подписывается 64-битным. Обратите внимание, что SQLite оптимизирует хранилище небольших целых чисел за кадром, поэтому TINYINT все равно не будет полезен.
  • REAL всегда 64-разрядный (double).
  • TEXT и BLOB имеют максимальный размер, определяемый макросом препроцессора, который по умолчанию равен 1 000 000 000 байт.

Ответ 3

Большинство из них существуют для совместимости. У вас действительно есть только целое число, float, text и blob. Даты могут быть сохранены как число (время unix - целое число, время Microsoft - float) или как текст.

Ответ 4

NULL. Значение представляет собой значение NULL.

INTEGER. Значение представляет собой целое число со знаком, сохраненное в 1, 2, 3, 4, 6 или 8 байтах в зависимости от величины значения.

REAL. Значение представляет собой значение с плавающей запятой, которое хранится как 8-байтовое число с плавающей точкой IEEE.

TEXT. Значение представляет собой текстовую строку, хранящуюся с использованием кодировки базы данных (UTF-8, UTF-16BE или UTF-16LE).

BLOB. Значение представляет собой блок данных, сохраненный точно так, как он был введен.

Ответ 5

В качестве дополнения к ответу от dan04, если вы хотите вслепую вставить NUMERIC, отличную от нуля, представленную TEXT, но убедитесь, что текст конвертируется в числовое:

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

Типичный пример использования - это запрос из программы, которая обрабатывает все данные как текст (для единообразия и простоты, поскольку SQLite уже делает это). Самое приятное в том, что он позволяет создавать такие конструкции:

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

что удобно, если вы используете заполнители, потому что вам не нужно обрабатывать такие ненулевые числовые поля. Пример с использованием модуля Python sqlite3 был бы,

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

В приведенном выше примере все значения в str_value_tuple будут экранированы и указаны как строки при передаче в SQlite. Однако, поскольку мы явно не проверяем тип с помощью TYPEOF, а только конвертируемость в тип, он будет по-прежнему работать по желанию (т.е. SQLite будет либо хранить его как числовое, либо не работать иначе).