Яка різниця між пов'язаними типами даних SQLite, такими як INT, INTEGER, SMALLINT та TINYINT?


101

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

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

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

Відповіді:


95

SQLiteВ технічному відношенні немає типів даних, в маніфестній системі набору тексту є класи зберігання , і так, це заплутано, якщо ви звикли до традиційних RDBMSес. Все, внутрішньо, зберігається як текст. Типи даних примушуються / перетворюються в різні місця зберігання на основі спорідненості (ала типи даних, призначені стовпцям).

Найкраще, що я рекомендую вам зробити:

  1. Тимчасово забудьте все, що раніше знали про окремі типи даних бази даних

  2. Прочитайте вищевказане посилання з SQLiteсайту.

  3. Візьміть типи, виходячи зі старої схеми, і подивіться, на що вони збираються SQLite

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

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


1
Дякуємо за відповідь та посилання. Чи означає це, що я повинен дотримуватися основних типів тексту, числових, цілих, реальних, жодних? Мені здається, це дуже обмежено, особливо з походження MSSQL, Foxpro та Oracle. З повагою
Алан Харріс-Рейд

6
Я згоден з вами, спочатку це здається обмеженим. Однак, я думаю, ви побачите, що SQLite дуже прощає в тому, як ви вводите дані в базу даних через її систему спорідненості. SQLite не є самостійним - він розроблений таким чином, щоб він був невеликим доповненням до бази даних, розміщеним у невеликих додатках, доступ до яких можна отримати лише за допомогою API доступу до бази даних у коді. Вирішення проблем у SQLite, як правило, полягає у з'ясуванні того, як вони хочуть, щоб ви це зробили.
Дж. Полфер

Я б дотримувався основних типів.
Дж. Полфер

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 байт.

1
Гарний трюк. Зверніть увагу, що цей підхід вимагає вставлення / оновлення значення, щоб мати той самий клас зберігання, як і в TYPEOF. Отже, спроби вставити ТЕКСТ, який інакше був би перетворений у клас зберігання NUMERIC / INTEGER за допомогою SQlite (тобто таке перетворення не втрачається відповідно до sqlite.org/datatype3.html#affinity ), не вдасться. Іншими словами, цей підхід суворіший, ніж спеціальний підхід до введення значення, а потім якось магічно підтверджує клас зберігання, який використовується для зберігання цього значення SQLite. Більш дозволений підхід дивіться у моїй відповіді нижче.
eold

10

Більшість із них є для сумісності. У вас дійсно є лише ціле число, float, текст та 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. Значення - це крапка даних, що зберігаються точно так, як було введено.


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 або зберігатиме його як числовий, або відмовляється інакше).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.