Какой тип данных MySQL использовать для хранения логических значений

943

Так как MySQL, похоже, не имеет никакого "логического" типа данных, какой тип данных вы "злоупотребляете" для хранения истинной/ложной информации в MySQL?

Особенно в контексте написания и чтения из/в PHP script.

Со временем я использовал и видел несколько подходов:

  • tinyint, поля varchar, содержащие значения 0/1,
  • поля varchar, содержащие строки '0'/'1' или 'true'/'false'
  • и, наконец, перечислить поля, содержащие два параметра: "true" / "false".

Ничто из вышеизложенного не кажется оптимальным. Я предпочитаю вариант tinyint 0/1, поскольку автоматическое преобразование типов в PHP дает мне логические значения довольно просто.

Какой тип данных вы используете? Есть ли тип, предназначенный для булевых значений, которые я забыл? Вы видите какие-либо преимущества/недостатки, используя тот или иной тип?

  • 200
    Любой, кто читает старые ответы на этот вопрос, должен понимать, что MySQL добавил немного типа данных в версии 5. Используйте эту информацию, как можете. dev.mysql.com/doc/refman/5.0/en/bit-type.html
  • 0
    Первый tinyint - это не поле varchar, как вы подразумевали выше. Ты имеешь в виду, что bigint - это тоже поле varchar? Во-вторых, я рекомендую tinyint для хранения логических полей.
Показать ещё 6 комментариев
Теги:
boolean
sqldatatypes

10 ответов

958
Лучший ответ

Для MySQL 5.0.3 и выше вы можете использовать BIT. В руководстве написано:

Начиная с MySQL 5.0.3, тип данных BIT используется для хранения битового поля значения. Тип BIT (M) позволяет хранить значения M-бит. M может варьироваться от 1 до 64.

В противном случае, согласно руководству MySQL, вы можете использовать bool и boolean, которые в настоящий момент являются псевдонимами tinyint (1):

Bool, Boolean: Эти типы являются синонимами для tinyint (1). Значение ноль считается ложным. Ненулевая значения считаются истинными.

MySQL также заявляет, что:

Мы намерены реализовать полное логическое типа в соответствии с стандартный SQL, в будущем MySQL выпуск.

Ссылки: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html

Кстати: это просто вопрос https://google.com/search?q=mysql+boolean+datatype.

Смешно, не так ли, эта ссылка, опубликованная несколько лет назад, стала рекурсивной.

  • 11
    Да, я бы выбрал это или CHAR (1) и сохранял бы «Y» / «N» или «T» / «F» и т. Д. В зависимости от контекста. Преимущество использования целочисленного типа малого размера состоит в том, что вы получаете максимальную переносимость через СУБД
  • 33
    Переход на char, по крайней мере в PHP, приведет к большему количеству кода, так как !$boolean никогда не оценит должным образом без дальнейшей обработки.
Показать ещё 32 комментария
181

BOOL и BOOLEAN являются синонимами TINYINT(1). Ноль false, все остальное true. Подробнее здесь.

  • 5
    (1) ничего не делает, кроме как определяет, как отображается значение. Если вы знаете размер хранилища, то вместо этого вы хотите использовать BIT
  • 30
    @JamesHalsall: На самом деле, BIT(1) и TINYINT(1) будут использовать один байт памяти. Вплоть до MySQL 5.0.3 BIT фактически был синонимом TINYINT . Более поздние версии MySQL изменили реализацию BIT. Но даже с изменением реализации, все еще нет никакого преимущества "размера хранилища" для типа данных BIT (по крайней мере, с InnoDB и MyISAM; другие механизмы хранения, например, NDB, могут иметь некоторую оптимизацию хранения для нескольких объявлений столбцов BIT.) Большая проблема заключается в том, что некоторые клиентские библиотеки не распознают или не обрабатывают должным образом возвращенные столбцы типа данных BIT . TINYINT работает лучше.
Показать ещё 3 комментария
64

Это изящное решение, которое я вполне понимаю, потому что он использует нулевые байты данных:

some_flag CHAR(0) DEFAULT NULL

Чтобы установить значение true, установите some_flag = '' и установите для него значение false, установите some_flag = NULL.

Затем, чтобы проверить значение true, проверьте, есть ли some_flag IS NOT NULL, и чтобы проверить значение false, проверьте, не some_flag IS NULL.

(Этот метод описан в разделе "Высокопроизводительная MySQL: оптимизация, резервное копирование, репликация и многое другое" Джона Уоррена Ленца, Барона Шварца и Арьена Ленца.)

  • 2
    модный трюк! это полезно, если вы работаете с MySQL <5 и, возможно, даже с меньшими затратами, чем BIT, однако, пытаясь выполнить соглашение и немного меньше вычислительных затрат (логика против точного значения), я бы сказал, что BIT - лучший путь.
  • 51
    Может быть «быстро», но это запутывает данные так, что любой новый разработчик не будет знать, что означает этот столбец.
Показать ещё 4 комментария
32

На этот вопрос был дан ответ, но я решил, что брошу свои $0,02. Я часто использую CHAR (0), где '' == true и NULL == false.

От mysql docs

CHAR (0) также очень приятно, когда вам нужен столбец, который может принимать только два значения: столбец, который определяется как CHAR (0) NULL, занимает только один бит и может принимать только значения NULL и '' (пустая строка).

  • 14
    мм, это похоже на проблему, если вы, как я. Я имею в виду, что в зависимости от языка может быть слишком просто не заметить разницу между NULL и '' (например, PHP).
  • 3
    С точки зрения экономии места (количество байтов, используемых для представления логического значения), этот подход является явным победителем. Это сохраняет байт над TINYINT. Недостатком (как отмечают некоторые комментарии) является то, что некоторые клиенты могут испытывать трудности при различении NULL и пустой строки. Даже некоторые реляционные базы данных (например, Oracle) не различают строку нулевой длины и NULL.
Показать ещё 2 комментария
22

Если вы используете тип BOOLEAN, это псевдоним TINYINT (1). Это лучше всего, если вы хотите использовать стандартизованный SQL и не против, чтобы поле могло содержать значение вне диапазона (в основном все, что не равно 0, будет "истинным" ).

ENUM ( "False", "True" ) позволит вам использовать строки в вашем SQL, а MySQL будет хранить это поле внутри себя как целое число, где "False" = 0 и "True" = 1 на основе порядка Указано Enum.

В MySQL 5+ вы можете использовать поле BIT (1) для указания 1-битного числового типа. Я не верю, что это фактически использует меньше места в хранилище, но снова позволяет ограничить возможные значения 1 или 0.

Все вышеперечисленное будет использовать примерно такое же количество памяти, поэтому лучше всего выбрать тот, с которым вы легко справитесь.

  • 8
    Ваше замечание относительно ENUM неверно: попробуйте CAST (yourenumcol AS UNSIGNED), и вы заметите, что False будет 1, а True будет 2. Другая проблема с ENUM заключается в том, что слишком легко вставить '' (пустая строка ) Я бы не рекомендовал использовать это.
  • 4
    По моему опыту, использование поля BIT (1) из кода PHP было немного хлопотно. TINYINT (1) был намного проще и создавал более читаемый код.
Показать ещё 3 комментария
14

Я использую TINYINT (1) для хранения логических значений в Mysql.

Я не знаю, есть ли какие-либо преимущества для использования этого... Но если я не ошибаюсь, mysql может хранить логическое значение (BOOL) и хранить его как tinyint (1)

http://dev.mysql.com/doc/refman/5.0/en/other-vendor-data-types.html

13

Бит полезен только по различным байтовым опциям (tinyint, enum, char (1)), если у вас много логических полей. Одно битовое поле по-прежнему занимает полный байт. Два битовых поля вписываются в тот же самый байт. Три, четыре, пять, шесть, семь, восемь. После чего они начинают заполнять следующий байт. В конечном итоге экономия настолько мала, что вам нужно сосредоточиться на тысячах других оптимизаций. Если вы не имеете дело с огромным количеством данных, эти несколько байтов не будут сильно отличаться. Если вы используете бит с PHP, вам нужно придать значения значениям входов и выходов.

  • 1
    +1 для комментария по типизации. Чтобы добавить к этому при работе с языками программирования, избегайте использования ленивых методов программирования в пользу последовательности. Используйте одинаковые операторы вместо просто равных. В случае PHP if ($ var == "") будет true для 0, false, null, undefined и "". для проверки всех значений часто лучше использовать if (true === empty ($ var)), поскольку это также позволит избежать неопределенных ошибок. Вам также следует проверить тип данных, с которым вы работаете, если (is_int ($ var) && $ var === 0) или привести его к типу, чтобы он стал конкретным типом данных (int) $ var для задачи.
  • 0
    @ Это правда для MySQL в той же степени, что и для MSSQL? Я перевожу новое приложение, которое еще не запущено в производство, с MSSQL на MySQL. Я не использую PHP, а скорее преобразую C # в Java 8. Учитывая, что Java является строго типизированным языком, я не беспокоюсь об обработке типов ... просто все битовые флаги, которые будут перемещаться от одного байта до 8 флагов к 1 байт каждого флага, заданного TINYINT (1). Знаете ли вы какую-либо документацию по этой теме для MySQL?
Показать ещё 1 комментарий
10

До тех пор, пока MySQL не реализует бит типа данных, если вы обрабатываете действительно нажатой для пространства и/или времени, например, с транзакциями с большим объемом, создайте поле TINYINT с именем bit_flags, для всех ваших логических переменных и маскируйте и сдвиньте boolean бит, который вы желаете в своем SQL-запросе.

Например, если ваш самый левый бит представляет ваше поле bool, а 7 самых правых бит ничего не представляют, тогда ваше поле бит_флаг будет равно 128 (двоичный 10000000). Маска (скрыть) семь самых правых бит (с помощью побитового оператора &) и сдвиньте 8-й бит семь пробелов вправо, в итоге получим 00000001. Теперь все число (которое в данном случае равно 1) - это ваше значение.

SELECT (t.bit_flags & 128) >> 7 AS myBool FROM myTable t;
if bit_flags = 128 ==> 1 (true)
if bit_flags = 0 ==> 0 (false)

Вы можете запускать такие утверждения, как при тестировании

SELECT (128 & 128) >> 7;

SELECT (0 & 128) >> 7;

и т.д...

Поскольку у вас есть 8 бит, у вас есть потенциально 8 логических переменных, начиная с одного байта. Некоторые будущие программисты будут неизменно использовать следующие семь бит, поэтому вы ДОЛЖНЫ маскироваться. Не просто сдвиньтесь, либо создадите ад для себя и других в будущем. Удостоверьтесь, что у вас есть маскировка и перенос MySQL - будет значительно быстрее, чем при использовании языка веб-скриптов (PHP, ASP и т.д.). Также убедитесь, что вы разместили комментарий в поле комментариев MySQL для своего поля бит_flags.

Вы найдете эти сайты полезными при реализации этого метода. http://dev.mysql.com/doc/refman/5.0/en/bit-functions.html http://acc6.its.brooklyn.cuny.edu/~gurwitz/core5/nav2tool.html

  • 6
    Это похоже на ужасный способ запутать намерения будущих программистов. Конечно, кажется, что это большая проблема, чтобы сохранить 7 байтов (при условии, что вы используете все 8 bools в этой единственной таблице!)
  • 0
    @ да нет никакого запутывания вообще! Напишите документацию и комментарии MySQL, объясняющие каждое поле в таблице (как упоминается в ответе)! Предложенная стратегия демаскирования MySQL выглядит солидно, и хранить до 16 различных логических полей всего с несколькими столбцами лучше, чем иметь 16 из них вместо этого. Если использование битовых манипуляций слишком сложно, и вы предпочитаете использовать свой язык веб-сценариев для получения каждого логического значения, просто сохраните его как VARCHAR и выполните процедуру демаскирования в коде (вам также не нужно ограничивать его 8 полями ) ...
7

Мне надоело пытаться получить нули, NULLS и "точно округлить петлю значений PHP, MySql и POST, поэтому я просто использую" Да "и" Нет ".

Это работает безупречно и не требует специального лечения, которое не является очевидным и легким в использовании.

  • 14
    Если вы действительно хотите потратить столько места и поставить под угрозу производительность, вы могли бы по крайней мере сделать CHAR (1) с опциями Y и N.
  • 3
    В большинстве реальных ситуаций существует реальная разница между «нет» и просто отсутствием информации. Например, вы можете установить флажок по умолчанию, если пользователь еще не сказал «нет». Как вы думаете, сколько именно места вы экономите, и сколько обработки вы выполняете каждый раз, когда вам нужно различать ложное и NULL - если вы вообще МОЖЕТЕ отличить? В мире хранимых изображений и цифрового видео один или два бита экономии места совершенно не имеют значения, но ясность и уменьшенная обработка реальны.
Показать ещё 3 комментария
3

Ссылаясь на эту ссылку   Boolean datatype в Mysql, в зависимости от использования приложения, если нужно сохранить только 0 или 1, лучше выбрать бит (1).

  • 6
    Это правда, что BIT(1) позволяет b'0' только значения b'0' или b'1' . Самая большая проблема с BIT данных BIT заключается в том, что различные клиентские библиотеки имеют различные возможности обработки этого типа. Изучите поведение в различных инструментах SQL (SQLyog, TOAD for MySQL, SQL Developer), инструментах, которые "восстанавливают" модели баз данных, и различных клиентах, таких как JDBC, PHP, Perl DBI, и для хорошей проверки протестируйте несколько сред ORM ( Hibernate, Mybatis, JPA). С точки зрения простоты использования, совместимости инструмента / фреймворка / нативной поддержки, TINYINT(1) - явный победитель.
  • 0
    Да. Завершение зависит от структуры, рассматриваемой для приложения. Например, PHP-инфраструктура Phalcon не обрабатывает битовый тип данных.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню