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

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

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

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

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

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

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

14.11.2008 10:36:18
Любой, кто читает старые ответы на этот вопрос, должен понимать, что MySQL добавил битовый тип данных в версии 5. Используйте эту информацию, как можете. dev.mysql.com/doc/refman/5.0/en/bit-type.html
smp7d 29.02.2012 14:51:35
tereško 25.07.2012 18:26:30
для текущей версии MYSQL доступен логический тип - dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html проверьте это. согласно этому значению ноль считается ложным
DevT 29.08.2012 08:51:02
bit(1)бит ** для импорта в Excel. Переход на tinyint(1)работы.
Cees Timmerman 18.02.2014 13:24:30
теперь у нас логическое значение через 5 лет
V-SHY 14.03.2014 09:54:52
12 ОТВЕТОВ
РЕШЕНИЕ

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

Начиная с MySQL 5.0.3, тип данных BIT используется для хранения значений битовых полей. Тип BIT (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

1222
11.11.2018 16:41:14
Да, я выбрал бы это или CHAR (1) и сохранял бы «Y» / «N» или «T» / «F» и т. Д. В зависимости от контекста. Преимущество использования целочисленного типа малого размера состоит в том, что вы получаете максимальную переносимость между RDBMS-es
Roland Bouman 15.05.2010 22:42:38
Переход на char, по крайней мере в PHP, приведет к большему количеству кода, !$booleanкоторый никогда не будет оцениваться должным образом без дальнейшей обработки.
Mild Fuzz 1.06.2011 20:58:20
@Pecerier Ничего, что ты не мог бы гуглить сам, но хорошо, я укушу. Прежде всего, пожалуйста, посмотрите на data0type.h. Обратите внимание, что innodb изначально не определяет тип BIT. Если бы он обрабатывал поля BIT так, как вы описываете, мы наверняка нашли бы там какой-то намек на его существование. Во-вторых, прочитайте mysqlperformanceblog.com/2008/04/23/… . И не стесняйтесь сообщить нам, какие замечательные клиенты MySQL в "marktetplace" хорошо работают с полями BIT. Они пригодятся тем, кто пропустил эту статью, без сомнения.
Roland Bouman 18.07.2012 22:02:05
Когда я делаю выбор из стандартной командной строки клиента mysql, битовые поля отображаются полностью пустыми. Из-за этого я предпочитаю TINYINT (1).
User 2.11.2012 00:53:33
@MikePurcell Я не хочу спрашивать, но зачем вам auto_incrementстолбец, представляющий логическое значение?
Chris Hayes 28.12.2013 09:13:06

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

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

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

18
14.11.2008 10:42:51

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

244
14.11.2008 10:55:02
Он (1)ничего не делает, кроме как определяет, как отображается значение, если вы знаете размер хранилища, то вы хотите использовать BITвместо этого
JamesHalsall 20.03.2014 09:09:14
@JamesHalsall: На самом деле, BIT(1)и TINYINT(1)оба будут использовать один байт памяти. Вплоть до MySQL 5.0.3 BITфактически был синонимом TINYINT. Более поздние версии MySQL изменили реализацию BIT. Но даже с изменением реализации, все еще нет никакого преимущества "размера хранилища" для BITтипа данных (по крайней мере, с InnoDB и MyISAM; другие механизмы хранения, например NDB, могут иметь некоторую оптимизацию хранения для нескольких объявлений столбцов BIT.) Большая проблема заключается в том, что какой-то клиент библиотеки не распознают или не обрабатывают должным образом возвращаемые BITстолбцы типов данных. А TINYINTработает лучше.
spencer7593 9.07.2014 19:37:50
В руководстве по MySQL 5.0 четко указано, что логическое значение равно 1 или 0. Фраза «все остальное есть true» не соответствует действительности.
Walter 23.01.2015 12:25:34
@ Вальтер: На самом деле, это своего рода правда, объяснения не хватает. Вкратце, в логическом контексте выражение может оцениваться как NULL, FALSE или TRUE. В операторе MySQL выражение, вычисленное в логическом контексте, сначала оценивается как целое число (десятичные значения и значения с плавающей запятой округляются, строки преобразуются обычным странным способом, которым MySQL преобразует строки в целое число). NULL, очевидно, NULL (ни ИСТИНА, ни ЛОЖЬ). Целочисленное значение 0 обрабатывается как FALSE, а любое другое целочисленное значение (1, 2, -7 и т. Д.) Оценивается как TRUE. Для совместимости мы имитируем эту логику / обработку логического значения
spencer7593 25.04.2015 01:45:24
@Walter: это легко проверить, например SELECT 'foo' AS bar FROM dual WHERE -7. Выражение -7 вычисляется в логическом контексте, и запрос возвращает строку. Мы можем проверить с 0 или любым выражением, которое оценивается как целочисленное значение 0, и строка не возвращается. Если выражение в предложении WHERE оценивается как любое ненулевое целочисленное значение, отличное от нуля, выражение имеет значение ИСТИНА. (Я полагаю, что десятичные значения и значения с плавающей точкой «округляются» до целого числа, например, WHERE 1/3оцениваются до WHERE 0. Мы получаем тот же результат с WHERE 'foo', потому что строка 'foo'также оценивается как целочисленное значение 0.
spencer7593 25.04.2015 01:50:19

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

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

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

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

34
14.11.2008 14:59:29
Ваше замечание относительно ENUM неверно: попробуйте CAST (yourenumcol AS UNSIGNED), и вы заметите, что False будет 1, а True будет 2. Другая проблема с ENUM заключается в том, что слишком легко вставить '' (пустая строка ) Я бы не рекомендовал использовать это.
Roland Bouman 15.05.2010 22:40:37
По моему опыту, использование поля BIT (1) из кода PHP было немного хлопотно. TINYINT (1) был намного проще и создавал более читаемый код.
M-Peror 21.07.2011 07:27:35
@ M-Peror - «использование поля BIT (1) из PHP-кода было немного хлопотно» ... не каламбур. :) Но да, я согласен. Я помню, что TINYINT (1) тоже был проще ... просто не могу вспомнить почему. У кого-нибудь еще есть мысли по этому поводу? BIT (1) кажется более приятным на первый взгляд, потому что вы можете ограничиться 0 или 1. Я думаю, что BIT иногда интерпретировали как двоичные данные (в зависимости от языка программирования и драйвера / библиотеки); в то время как TINYINT рассматривался больше как число.
BMiner 6.12.2011 19:29:15
@BMiner - ха-ха, это было действительно непреднамеренно, я этого не заметил :) Но действительно, если я правильно помню, битовое поле интерпретировалось как нечто двоичное, тогда как tinyint было легче воспринимать как число, и поэтому легче использовать в (логическом) выражении.
M-Peror 21.12.2011 07:59:50

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

Из документации MySQL :

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

34
19.04.2020 11:25:39
мм, это похоже на проблемы, если вы, как я. Я имею в виду, что в зависимости от языка может быть слишком просто не заметить разницу между NULL и '' (например, PHP).
Roland Bouman 15.05.2010 22:36:28
С точки зрения экономии места (количество байтов, используемых для представления логического значения), этот подход является явным победителем. Это сохраняет байт над TINYINT. Недостатком (как отмечают некоторые комментарии) является то, что некоторые клиенты могут испытывать трудности при различении NULL и пустой строки. Даже некоторые реляционные базы данных (например, Oracle) не различают строку нулевой длины и NULL.
spencer7593 10.06.2015 14:15:06
Это очень умно! Раньше я писал умный код, теперь я избегаю его, как чумы. Теперь я хочу, чтобы мой код имел кристально чистое намерение, а не только правильное поведение. Мой совет? Делайте это только если вы хотите сбить с толку тех, кто поддерживает код / ​​базу данных. Например, в PHP оба ''и nullявляются ложными значениями.
CJ Dennis 15.05.2018 06:30:25
@CJDennis Если вы абстрагировали слой своей базы данных за шаблоном репозитория, вам не нужно беспокоиться о неясности этого решения.
prograhammer 31.01.2019 02:14:00

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

Например, если ваш самый левый бит представляет ваше поле bool, а 7 самых правых битов ничего не представляют, тогда ваше bit_flagsполе будет равно 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 для своего bit_flagsполя.

Вы найдете эти сайты полезными при реализации этого метода:

12
22.06.2018 16:09:32
Это похоже на ужасный способ запутать намерения будущих программистов. Конечно, кажется большим трудом сохранить 7 байтов (при условии, что вы используете все 8 bools в этой единственной таблице!)
yep 15.07.2011 18:24:38
@ да нет никакого запутывания вообще! Напишите документацию и комментарии MySQL, объясняющие каждое поле в таблице (как упоминается в ответе)! Предлагаемая стратегия демаскирования MySQL выглядит солидно, и лучше хранить до 16 различных логических полей с парой столбцов, чем иметь 16 из них. Если использование битовых манипуляций слишком сложно, и вы предпочитаете использовать свой язык веб-сценариев для получения каждого логического значения, просто сохраните его как a VARCHARи выполните процедуру демаскирования в коде (вам также не нужно ограничивать его 8 полями) ...
CPHPython 9.05.2018 11:00:48
BITТипа существует. См. Dev.mysql.com/doc/refman/8.0/en/bit-type.html
dolmen 5.11.2019 16:12:07

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

17
12.01.2012 16:18:54
+1 для комментария по типизации. Чтобы добавить к этому при работе с языками программирования, избегайте использования ленивых методов программирования в пользу последовательности. Используйте одинаковые операторы вместо просто равных. В случае PHP if ($ var == "") будет true для 0, false, null, undefined и "". для проверки всех значений часто лучше использовать if (true === empty ($ var)), поскольку это также позволит избежать неопределенных ошибок. Вам также следует проверить тип данных, с которым вы работаете, если (is_int ($ var) && $ var === 0) или типизировать его, чтобы он стал конкретным типом данных (int) $ var для задачи.
fyrye 17.01.2014 01:35:12
@ Это правда для MySQL в той же степени, что и для MSSQL? Я перевожу новое приложение, которое еще не запущено в производство, с MSSQL на MySQL. Я не использую PHP, а скорее преобразую C # в Java 8. Учитывая, что Java является строго типизированным языком, я не беспокоюсь об обработке типов ... просто все битовые флаги, которые будут перемещаться от одного байта до 8 флагов к 1 байт каждого флага, заданного TINYINT (1). Знаете ли вы какую-либо документацию по этой теме для MySQL?
Zack Jannsen 2.02.2016 20:29:47
@Thor Проведя более глубокое исследование, ясно, каким должен быть ответ. Изменения происходят, и мы увидели улучшения в этой обработке. Знайте свой язык, который будет на уровне приложений / уровне доступа к данным, и знайте, что ваши библиотеки поддерживают. В настоящее время я использую Java, и в настоящее время рекомендуется использовать BIT (1) для таких библиотек, как Hybernate и JDBC. Вот URL [см. Таблицу 5.2]: dev.mysql.com/doc/connector-j/en/…
Zack Jannsen 3.02.2016 11:43:01

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

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: оптимизация, резервное копирование, репликация и многое другое» Джона Уоррена Ленца, Барона Шварца и Арьена Ленца.)

70
19.12.2016 20:36:12
модный трюк! это полезно, если вы работаете с MySQL <5 и, возможно, даже с меньшими затратами, чем BIT, однако, пытаясь выполнить соглашение и немного меньше вычислительных затрат (логика против точного значения), я бы сказал, что BIT - лучший путь.
zamnuts 13.08.2012 19:28:40
Может быть «быстро», но это запутывает данные так, что любой новый разработчик не будет знать, что означает этот столбец.
Richthofen 2.04.2013 18:16:54
Это использует то же количество байтов, что и BIT (1)
ITS Alaska 25.04.2013 18:18:19
Удачи вам в получении ORM, который будет хорошо отображать это.
Craig Labenz 3.08.2013 21:55:47
Я согласен с @Richthofen и мне трудно представить ситуацию, в которой я бы когда-либо выступал за использование этого решения. Однако, если он будет использоваться, то указание в качестве определения COMMENTв столбце, которое NULLуказывает на ложь и ''указывает на истину, может пойти очень маленьким путем, помогающим понять будущее.
eggyal 21.03.2015 11:52:26

Я сыт по горло попытками получить нули, NULLS и «точно» в цикле значений PHP, MySql и POST, поэтому я просто использую «Да» и «Нет».

Это работает безупречно и не требует особой обработки, которая не очевидна и проста в исполнении.

10
3.08.2017 13:55:53
Если вы действительно хотите потратить столько места и поставить под угрозу производительность, вы могли бы по крайней мере сделать CHAR (1) с опциями Y и N.
ILikeTacos 19.09.2013 13:42:12
В большинстве реальных ситуаций существует реальная разница между «нет» и просто отсутствием информации. Например, вы можете установить флажок по умолчанию, если пользователь еще не сказал «нет». Как вы думаете, сколько именно места вы экономите, и сколько обработки вы выполняете каждый раз, когда вам нужно различать ложное и NULL - если вы вообще МОЖЕТЕ отличить? В мире сохраненных изображений и цифрового видео один или два бита экономии пространства совершенно не имеют значения, но ясность и уменьшенная обработка реальны.
Geoff Kendall 6.08.2014 11:59:19
Этот ответ не является неправильным, потому что он будет работать, и он не так плох, как люди считают, что это правильно. Для большинства проектов (то есть: размеры таблиц <1 мил строк) Различия в производительности между предоставленными решениями будут незначительными. Я не буду жаловаться, если мои запросы возвращаются через 7 против 5 миллисекунд ... Если быть честным, хотя, если ваши таблицы растут в 10 миллионов строк или более, это, вероятно, не является предпочтительным решением.
Brad 29.09.2014 19:05:16
+1 от меня за использование типа данных ENUM. Я лично предпочитаю это обозначение: ENUM ('y', 'n'). Он компактен (всего в байтах), интуитивно понятен и хорошо выглядит как соглашение уровня приложения для всех логических флагов. Вы можете использовать его непосредственно с полями формы HTML. например, для PHP: <select name = "production"> <option value = "y" <? = $ production === 'y'? 'selected = "selected"': ''? >> Да </ option> <option value = "n" <? = $ production === 'n'? 'selected = "selected"': ''? >> Нет </ option> </ select>
Vlado 14.10.2014 09:34:58
Lol это поймал мой взгляд, но я должен сказать, что @GeoffKendall прав. В большинстве случаев нет необходимости в оптимальной производительности, и какой бы метод ни выполнял работу для вас, это правильный метод.
Madmenyo 12.09.2015 14:17:55

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

6
13.04.2017 12:42:36
Это правда, что BIT(1)только позволит b'0'или b'1'значение будет сохранено. Самая большая проблема с BITтипом данных заключается в том, что различные клиентские библиотеки имеют различные возможности обработки этого типа данных. Изучите поведение в различных инструментах SQL (SQLyog, TOAD for MySQL, SQL Developer), инструментах, которые «восстанавливают» модели баз данных, а также на различных клиентах, таких как JDBC, PHP, Perl DBI, и, если хотите, протестируйте несколько сред ORM ( Hibernate, Mybatis, JPA). С точки зрения простоты использования, инструментальная / совместимость с фреймворком / нативная поддержка TINYINT(1)- явный победитель.
spencer7593 25.04.2015 02:13:45
Да. Завершение зависит от структуры, рассматриваемой для приложения. Например, среда PHP Phalcon не поддерживает тип данных Bit
Vidz 28.04.2015 05:54:23
Для записи, MyBatis поддерживает BITи TINYINT. Обратитесь к классу MyBatis JdbcType, mybatis.org/mybatis-3/apidocs/reference/org/apache/ibatis/type/…
Lucky 31.12.2015 14:03:14
@Vidz Я даю вам плюс один за упоминание BIT (1), но также хотел бы указать разработчикам, читающим это: знайте свой язык, который будет на уровне приложений / уровне доступа к данным, и знайте, что ваши библиотеки поддерживают. В настоящее время я использую Java, и в настоящее время рекомендуется использовать BIT (1) для таких библиотек, как Hybernate и JDBC. Вот URL [см. Таблицу 5.2]: dev.mysql.com/doc/connector-j/en/…
Zack Jannsen 3.02.2016 11:38:47

Прочитав ответы здесь, я решил использовать, bit(1)и да, это как-то лучше в пространстве / времени, НО через некоторое время я передумал и никогда больше не буду его использовать. Это сильно усложнило мою разработку при использовании готовых операторов, библиотек и т. Д. (Php).

С тех пор я всегда использую tinyint(1), кажется, достаточно хорошо.

2
26.06.2018 10:14:10
Не могли бы вы объяснить, как это осложнило ваше развитие?
Chazy Chaz 20.12.2018 19:08:44
@ChazyChaz ожидает true / false вместо 1/0, в отличие от некоторых других БД, таких как SQL Server. Иногда это может привести к странным ситуациям, когда вы думаете, что устанавливаете его на true, но на самом деле этого не происходит.
maembe 31.05.2019 14:18:32

Поскольку MySQL (8.0.16) и MariaDB (10.2.1) реализовали ограничение CHECK, я бы сейчас использовал

bool_val TINYINT CHECK(bool_val IN(0,1))

Вы сможете только в магазине 0, 1или NULL, а также значения , которые могут быть преобразованы в 0или 1без ошибок , как '1', 0x00, b'1'или TRUE/ FALSE.

Если вы не хотите разрешать NULL, добавьте NOT NULLопцию

bool_val TINYINT NOT NULL CHECK(bool_val IN(0,1))

Обратите внимание, что практически нет разницы, если вы используете TINYINT, TINYINT(1)или TINYINT(123).

Если вы хотите, чтобы ваша схема была совместимой вверх, вы также можете использовать BOOLилиBOOLEAN

bool_val BOOL CHECK(bool_val IN(TRUE,FALSE))

db <> Fiddle demo

6
26.05.2019 17:53:19
что насчет enum (0, 1)
santiago arizti 8.08.2019 22:55:38
@santiagoarizti ENUM(должно быть, enum('0', '1')обратите внимание: это строки) не очень хорошая идея. Есть слишком много вопросов , из - за того , как она хранится внутри, и как нестроковые значения обрабатываются. Например. 0и FALSE не может быть сохранен. 1и TRUEстать '0'. И 2становится '1'.
Paul Spiegel 9.08.2019 07:11:31
Лучший ответ ... для тех, кто использует MySQL 8+
dolmen 5.11.2019 16:17:28