При создании таблицы в SQLite3 я запутываюсь, когда сталкиваюсь со всеми возможными типами данных, которые подразумевают сходное содержимое, поэтому может ли кто-нибудь сказать мне разницу между следующими типами данных?
INT, INTEGER, SMALLINT, TINYINT
DEC, DECIMAL
LONGCHAR, LONGVARCHAR
DATETIME, SMALLDATETIME
Есть ли какая-то документация где-то, где перечисляется min./max. емкости различных типов данных? Например, я полагаю, что smallint
имеет большее максимальное значение, чем tinyint
, но меньшее значение, чем целое число, но я не знаю, что это за возможности.
SQLite
, технически, не имеет типов данных, есть классы хранения в системе набора символов, и да, это сбивает с толку, если вы 'используется для традиционных RDBMS
es. Все, внутренне, хранится как текст. Типы данных принудительно/конвертируются в различные места хранения на основе аффинностей (типы данных ala, назначенные столбцам).
Лучшее, что я рекомендую вам сделать, это:
Временно забыть все, что вы знали о автономных типах данных базы данных
Прочитайте приведенную выше ссылку с сайта SQLite
.
Возьмите типы, основанные на старой схеме, и посмотрите, на что они будут сопоставляться в SQLite
Перенесите все данные в базу данных SQLite
.
Примечание. Ограничения типа данных могут быть громоздкими, особенно если вы добавляете длительность времени или даты или такие вещи в SQL
. SQLite
имеет очень мало встроенных функций для такого рода вещей. Тем не менее, SQLite
предоставляет вам простой способ сделать ваши собственные встроенные функции для добавления продолжительности времени и вещей такого характера через sqlite3_create_function
функция библиотеки. Вы использовали бы это средство вместо традиционных хранимых процедур.
Разница заключается в синтаксическом сахаре. Только несколько подстрок имен типов имеют значение как сродство типа.
Правила определения сродства перечислены на сайте 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 байт.TYPEOF
. Поэтому попытки вставить TEXT, который в противном случае был бы преобразован в класс хранения NUMERIC / INTEGER с помощью SQlite (т. Е. Такое преобразование без потерь согласно sqlite.org/datatype3.html#affinity ), потерпели бы неудачу. Другими словами, этот подход является более строгим, чем специальный подход, заключающийся в вставке значения и последующей магической проверке класса хранения, используемого для хранения этого значения в SQLite. Для более разрешительного подхода, см. Мой ответ ниже.
Большинство из них существуют для совместимости. У вас действительно есть только целое число, float, text и blob. Даты могут быть сохранены как число (время unix - целое число, время Microsoft - float) или как текст.
NULL
. Значение представляет собой значение NULL.
INTEGER
. Значение представляет собой целое число со знаком, сохраненное в 1, 2, 3, 4, 6 или 8 байтах в зависимости от величины значения.
REAL
. Значение представляет собой значение с плавающей запятой, которое хранится как 8-байтовое число с плавающей точкой IEEE.
TEXT
. Значение представляет собой текстовую строку, хранящуюся с использованием кодировки базы данных (UTF-8, UTF-16BE или UTF-16LE).
BLOB
. Значение представляет собой блок данных, сохраненный точно так, как он был введен.
В качестве дополнения к ответу от 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 будет либо хранить его как числовое, либо не работать иначе).