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

101

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

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

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

Алан Харрис-Рид
источник

Ответы:

95

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

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

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

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

  3. Возьмите типы, основанные на вашей старой схеме, и посмотрите, что они будут отображать в SQLite

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

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

Дж. Польфер
источник
1
Спасибо за ответ и ссылку. Означает ли это, что я должен придерживаться основных типов текста: числовой, целочисленный, вещественный, никакой? Мне кажется очень ограниченным, особенно если я имею опыт работы с MSSQL, Foxpro и Oracle. С уважением.
Алан Харрис-Рид,
6
Я согласен с вами, сначала это кажется ограниченным. Тем не менее, я думаю, вы обнаружите, что SQLite очень снисходителен к тому, как вы помещаете данные в базу данных через свою систему сродства. SQLite не является автономным - он разработан как небольшая серверная часть базы данных, которую вы размещаете в небольших приложениях для доступа только через API доступа к базе данных в коде. Решение проблем в SQLite обычно сводится к выяснению того, как они хотят, чтобы вы это делали.
J. Polfer
Я бы остановился на основных типах.
J. Polfer
4
@Alan: Возможно, вам будет полезно объявить столбцы числового сродства как DATEили BOOLEAN, но я бы не стал различать разные размеры целых чисел. Это особенно верно для случая INTEGER PRIMARY KEY, когда точное имя типа имеет значение.
dan04
«Все хранится как текст» кажется неправильным согласно sqlite.org/fileformat.html , где говорится, что числа хранятся как компактные varints / float64, и только blob и текст хранятся как строки
phiresky
47

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

  • 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 байт.
dan04
источник
1
Хороший трюк. Обратите внимание, что этот подход требует , чтобы вставляемое / обновляемое значение имело тот же класс хранения, что и значение в TYPEOF. Таким образом, попытки вставить ТЕКСТ, который в противном случае был бы преобразован в класс хранения NUMERIC / INTEGER с помощью SQlite (т. Е. Такое преобразование без потерь, согласно sqlite.org/datatype3.html#affinity ) потерпят неудачу. Другими словами, этот подход более строгий, чем специальный подход, когда значение вставляется, а затем каким-то волшебным образом проверяется класс хранилища, используемый для хранения этого значения SQLite. Чтобы узнать о более снисходительном подходе, см. Мой ответ ниже.
eold
10

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

Джей
источник
Я использовал его для веб-проектов, где в конечном итоге все в конечном итоге все равно помещалось на html-страницу. Я отказался от большого количества преобразований данных и просто использовал текст для большинства столбцов. Это хорошо сработало.
Джей
3

NULL. Это значение NULL.

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

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

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

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

user2393484
источник
1

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

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

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

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

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

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 либо сохранит его как числовое, либо не сработает).

eold
источник