Qué tipo de datos MySQL usar para almacenar valores booleanos

Dado que MySQL no parece tener ningún tipo de datos 'booleano', ¿de qué tipo de datos 'abusa' para almacenar información verdadera / falsa en MySQL?

Especialmente en el contexto de escribir y leer desde / hacia un script PHP.

Con el tiempo, he usado y visto varios enfoques:

  • tinyint, campos varchar que contienen los valores 0/1,
  • campos varchar que contienen las cadenas '0' / '1' o 'verdadero' / 'falso'
  • y finalmente enum Fields que contienen las dos opciones 'true' / 'false'.

Ninguno de los anteriores parece óptimo. Tiendo a preferir la variante tinyint 0/1, ya que la conversión automática de tipos en PHP me da valores booleanos de manera bastante simple.

Entonces, ¿qué tipo de datos usas? ¿Existe un tipo diseñado para valores booleanos que he pasado por alto? ¿Ve alguna ventaja / desventaja al usar un tipo u otro?

preguntado el 14 de noviembre de 08 a las 08:11

Cualquiera que esté leyendo las respuestas anteriores a esta pregunta debe comprender que MySQL agregó un tipo de datos bit en la versión 5. Use esa información como pueda. dev.mysql.com/doc/refman/5.0/en/bit-type.html -

para la versión actual de MYSQL, el tipo booleano está disponible- dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html Mira esto. según ese valor cero considerado falso -

bit(1)es un poco ** para importar en Excel. Cambiar a tinyint(1) obras. -

ahora tenemos booleano después de 5 años -

13 Respuestas

Para MySQL 5.0.3 y superior, puede usar BIT. El manual dice:

A partir de MySQL 5.0.3, el tipo de datos BIT se utiliza para almacenar valores de campo de bits. Un tipo de BIT (M) permite el almacenamiento de valores de M-bit. M puede oscilar entre 1 y 64.

De lo contrario, de acuerdo con el manual de MySQL, puede usar BOOL or BOOLEAN, que en este momento son alias de diminuto(1):

Bool, booleano: estos tipos son sinónimos de TINYINT(1). Un valor de cero se considera falso. Los valores distintos de cero se consideran verdaderos.

MySQL también establece que:

Tenemos la intención de implementar el manejo completo de tipos booleanos, de acuerdo con SQL estándar, en una futura versión de MySQL.

Referencias: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html

Respondido 24 ago 20, 07:08

Sí, iría por esto o por un CHAR (1) y almacenaría 'Y' / 'N' o 'T' / 'F', etc., según el contexto. La ventaja de usar un tipo de entero pequeño es que obtiene la máxima portabilidad en RDBMS-es - Roland Bouman

Ir a char, al menos en PHP, conducirá a más código como !$boolean nunca evaluará adecuadamente sin un procesamiento adicional. - Pelusa leve

@Pecerier Nada que no pudieras buscar en Google, pero bueno, morderé. En primer lugar, eche un vistazo a data0type.h. Tenga en cuenta que innodb no define de forma nativa un tipo BIT allí. Si tratara los campos BIT de la manera que usted describe, seguramente encontraríamos algún indicio de su existencia allí. En segundo lugar, lea mysqlperformanceblog.com/2008/04/23/…. Y no dude en explicarnos qué asombrosos clientes MySQL en el "marktetplace" funcionan bien con los campos BIT. Serán útiles para quien se haya perdido ese artículo, sin duda. - Roland Bouman

Cuando hago una selección de la línea de comandos estándar de mysql, los campos de bits del cliente aparecen completamente en blanco. Por eso prefiero TINYINT (1). - Usuario

@MikePurcell Odio preguntar, pero ¿por qué querrías? auto_increment en una columna que representa un valor booleano? - Chris Hayes

BOOL y BOOLEAN son sinónimos de TINYINT(1). Cero es false, cualquier otra cosa es true. Más información aquí.

respondido 14 nov., 08:10

EL (1) no hace nada más que determinar cómo se muestra el valor, si está consciente del tamaño de almacenamiento, entonces desea usar BIT en lugar de - James Halsall

@JamesHalsall: En realidad, BIT(1) y TINYINT(1) Ambos utilizarán un byte de almacenamiento. Hasta MySQL 5.0.3, BIT era en realidad un sinónimo de TINYINT. Las versiones posteriores de MySQL cambiaron la implementación de BIT. Pero incluso con el cambio de implementación, todavía no hay ningún beneficio de "tamaño de almacenamiento" para el BIT tipo de datos (al menos con InnoDB y MyISAM; otros motores de almacenamiento, por ejemplo, NDB pueden tener alguna optimización de almacenamiento para declaraciones de columnas BIT múltiples). El problema más grande es que algunas bibliotecas cliente no reconocen o manejan apropiadamente las devoluciones BIT columnas de tipo de datos. A TINYINT funciona mejor. - spencer7593

El manual de MySQL 5.0 dice claramente que un valor booleano es 1 o 0. La frase "cualquier otra cosa es true" no es verdad. - Walter

@Walter: En realidad es cierto, la explicación es algo deficiente. Brevemente, en un contexto booleano, una expresión se puede evaluar como NULL, FALSE o TRUE. En una declaración de MySQL, una expresión evaluada en un contexto booleano se evalúa primero como un número entero (los valores decimales y flotantes se redondean, las cadenas se convierten de la manera peculiar habitual que MySQL convierte las cadenas en números enteros). Un NULL es obviamente NULL (ni VERDADERO ni FALSO). Un valor entero de 0 se maneja como FALSO y cualquier otro valor entero (1, 2, -7, etc.) se evalúa como VERDADERO. Por compatibilidad, imitamos esa lógica / manejo de TINYINT boolean - spencer7593

@Walter: esto es fácil de probar, p. Ej. SELECT 'foo' AS bar FROM dual WHERE -7. La expresión -7 se evalúa en un contexto booleano y la consulta devuelve una fila. Podemos probar con 0, o cualquier expresión que se evalúe como un valor entero 0, y no se devuelve ninguna fila. Si la expresión en la cláusula WHERE se evalúa como cualquier valor entero no nulo que no sea cero, la expresión es VERDADERA. (Creo que los valores decimales y flotantes se "redondean" a números enteros, p. Ej. WHERE 1/3 evalúa a WHERE 0. Obtenemos el mismo resultado con WHERE 'foo', porque cuerda 'foo' también evalúa al valor entero 0. - spencer7593

Esta es una solución elegante que aprecio bastante porque usa bytes de datos cero:

some_flag CHAR(0) DEFAULT NULL

Para establecerlo en verdadero, establezca some_flag = '' y para establecerlo en falso, establezca some_flag = NULL.

Luego, para probar si es cierto, verifique si some_flag IS NOT NULL, y para probar si es falso, verifique si some_flag IS NULL.

(Este método se describe en "MySQL de alto rendimiento: optimización, copias de seguridad, replicación y más" por Jon Warren Lentz, Baron Schwartz y Arjen Lentz).

Respondido el 19 de diciembre de 16 a las 20:12

truco de fantasía! esto es útil si se trabaja con MySQL <5 y quizás incluso una huella más liviana que BIT, sin embargo, en un esfuerzo por cumplir con la convención y un poco menos de sobrecarga de cálculo (lógica frente a valor exacto), diría que BIT es la mejor manera de hacerlo. - zamnuts

Puede que sea "rápido", pero confunde los datos de modo que cualquier desarrollador nuevo no tenga idea de lo que representa la columna. - Richthofen

Esto usa la misma cantidad de bytes que BIT (1) - SU Alaska

Buena suerte consiguiendo un ORM que se asigne bien a esto. - craig labenz

Estoy de acuerdo con @Richthofen y me resulta difícil imaginar una situación en la que alguna vez abogaría por el uso de esta solución. Sin embargo, si se va a utilizar, especificar como COMMENT en la definición de la columna que NULL indica falso y '' indica que verdadero podría contribuir de alguna manera muy pequeña a ayudar a la comprensión futura. - huevo

Esta pregunta ha sido respondida, pero pensé que arrojaría mis $ 0.02. A menudo uso un CHAR(0), Donde '' == true and NULL == false.

Desde documentos mysql:

CHAR(0) también es bastante bueno cuando necesita una columna que puede tomar solo dos valores: Una columna que se define como CHAR(0) NULL ocupa solo un bit y puede tomar solo los valores NULL y '' (la cadena vacía).

Respondido 19 Abr '20, 12:04

mm, esto parece buscar problemas si eres como yo. Quiero decir, dependiendo del idioma, puede ser demasiado fácil no detectar la diferencia entre NULL y '' (por ejemplo, PHP). - Roland Bouman

En términos de ahorro de espacio (la cantidad de bytes utilizados para representar un booleano), este enfoque es un claro ganador. Esto ahorra un byte sobre TINYINT. La desventaja (como señalan algunos comentarios) es que algunos clientes pueden tener dificultades para distinguir entre una cadena NULL y una vacía. Incluso algunas bases de datos relacionales (por ejemplo, Oracle) no distinguen entre una cadena de longitud cero y una NULL. - spencer7593

¡Esto es muy inteligente! Solía ​​escribir código inteligente, ahora lo evito como la plaga. Ahora quiero que mi código tenga una intención muy clara, no solo un comportamiento correcto. ¿Mi consejo? Solo haga esto si desea confundir a cualquiera que tenga que admitir el código / base de datos. Por ejemplo, en PHP tanto '' y null son valores falsos. - dennis cj

@CJDennis Si ha abstraído la capa de su base de datos detrás del patrón de repositorio, no tiene que preocuparse por la oscuridad de esta solución. - programador

Si utiliza el tipo BOOLEAN, se le asignará el alias de TINYINT (1). Esto es mejor si desea utilizar SQL estandarizado y no le importa que el campo pueda contener un valor fuera de rango (básicamente, cualquier cosa que no sea 0 será "verdadero").

ENUM ('False', 'True') le permitirá usar las cadenas en su SQL, y MySQL almacenará el campo internamente como un número entero donde 'False' = 0 y 'True' = 1 según el orden en que se especifique la enumeración .

En MySQL 5+ puede usar un campo BIT (1) para indicar un tipo numérico de 1 bit. No creo que esto realmente use menos espacio en el almacenamiento, pero nuevamente le permite restringir los valores posibles a 1 o 0.

Todo lo anterior utilizará aproximadamente la misma cantidad de almacenamiento, por lo que es mejor elegir el que le resulte más fácil trabajar.

respondido 14 nov., 08:14

Su comentario sobre ENUM no es cierto: intente CAST (yourenumcol AS UNSIGNED) y notará que False será 1 y True será 2. Otro problema con ENUM es que es demasiado fácil de insertar '' (cadena vacía ). No recomendaría usar esto. - Roland Bouman

En mi experiencia, usar un campo BIT (1) del código PHP fue un poco problemático. TINYINT (1) fue mucho más fácil y produjo un código más legible. - M-Peror

@ M-Peror - "usar un campo BIT (1) del código PHP era una poco problemático "... sin juego de palabras. :) Pero, sí, estoy de acuerdo. Recuerdo que TINYINT (1) también es más fácil ... simplemente no puedo recordar por qué. ¿Alguien más tiene pensamientos sobre esto? BIT (1) parece más agradable en la superficie porque puede restringir a 0 o 1. Creo que BIT a veces se interpretó como datos binarios (según el lenguaje de programación y el controlador / biblioteca); mientras que, TINYINT se trató más como un número. BMINER

@BMiner - jaja, fue realmente involuntario, no me di cuenta de eso :) Pero de hecho, si recuerdo correctamente, el campo de bits se interpretó como algo binario, mientras que el tinyint fue más fácil de tratar como un número y, por eso, más fácil de utilizar en una expresión (booleana). - M-Peror

Utilizo TINYINT (1) para almacenar valores booleanos en Mysql.

No sé si hay alguna ventaja para usar esto ... Pero si no me equivoco, mysql puede almacenar boolean (BOOL) y lo almacena como un tinyint (1)

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

respondido 14 nov., 08:10

Bit solo es ventajoso sobre las diversas opciones de bytes (tinyint, enum, char (1)) si tiene muchos campos booleanos. El campo de un bit todavía ocupa un byte completo. Dos campos de bits caben en ese mismo byte. Tres, cuatro, cinco, seis, siete, ocho. Después de lo cual comienzan a llenar el siguiente byte. En última instancia, los ahorros son tan pequeños que hay miles de otras optimizaciones en las que debería centrarse. A menos que esté tratando con una enorme cantidad de datos, esos pocos bytes no sumarán mucho. Si está utilizando bit con PHP, debe encasillar los valores que entran y salen.

Respondido el 12 de enero de 12 a las 16:01

+1 para el comentario de encasillado. Para agregar a esto, cuando trabaje con lenguajes de programación, evite usar técnicas de programación perezosas en favor de la coherencia. Utilice operadores idénticos en lugar de solo iguales. En el caso de PHP, if ($ var == "") será verdadero para 0, falso, nulo, indefinido y "". para probar todos los valores, a menudo es mejor usar if (true === empty ($ var)) ya que también evitará los errores no definidos. También debe validar el tipo de datos con el que está trabajando if (is_int ($ var) && $ var === 0) o convertirlo en un tipo de datos específico (int) $ var para la tarea. - Será.

@Thor, ¿esto es cierto para MySQL en la misma medida que lo es para MSSQL? Estoy migrando una nueva aplicación que aún no ha entrado en producción de MSSQL a MySQL. No estoy usando PHP, sino más bien convirtiendo C # a Java 8. Dado que Java es un lenguaje fuertemente tipado, no me preocupa el manejo de tipos ... solo todos los indicadores de bits que se moverían de un byte para hasta 8 indicadores a 1 byte por cada bandera dada TINYINT (1). ¿Conoce alguna documentación sobre este tema para MySQL? - Zack Jansen

@Thor Al hacer una investigación más profunda, está claro cuál debería ser la respuesta. El cambio ocurre y hemos visto mejoras en este manejo. Conozca su idioma que estará en la capa de aplicación / capa de acceso a datos y conozca el soporte de sus bibliotecas. Actualmente estoy usando Java y BIT (1) es la opción recomendada en este momento para bibliotecas como Hybernate y el uso de JDBC. Aquí está la URL [Ver tabla 5.2]: dev.mysql.com/doc/conector-j/en/… - Zack Jansen

demuestre con un enlace de recursos que las columnas de 8 bits (1) toman el mismo byte ... He buscado por un tiempo y en ninguna parte lo he encontrado ... - asensi

Hasta que MySQL implemente un tipo de datos bit, si su procesamiento está realmente presionado por espacio y / o tiempo, como con transacciones de alto volumen, cree un campo TINYINT llamado bit_flags para todas sus variables booleanas, y enmascare y cambie el bit booleano que desee en su consulta SQL.

Por ejemplo, si su bit más a la izquierda representa su campo bool, y los 7 bits más a la derecha no representan nada, entonces su bit_flags El campo será igual a 128 (binario 10000000). Enmascare (oculte) los siete bits más a la derecha (usando el operador bit a bit &), y mueva el octavo bit siete espacios a la derecha, terminando con 8. Ahora el número completo (que, en este caso, es 00000001) es su valor.

SELECT (t.bit_flags & 128) >> 7 AS myBool FROM myTable t;

if bit_flags = 128 ==> 1 (true)
if bit_flags = 0 ==> 0 (false)

Puede ejecutar declaraciones como estas mientras prueba

SELECT (128 & 128) >> 7;

SELECT (0 & 128) >> 7;

etc.

Como tiene 8 bits, tiene potencialmente 8 variables booleanas de un byte. Algún programador futuro utilizará invariablemente los siguientes siete bits, por lo que debe: máscara. No se limite a cambiar, o creará un infierno para usted y los demás en el futuro. Asegúrese de que MySQL haga su enmascaramiento y cambio; esto será significativamente más rápido que tener el lenguaje de scripting web (PHP, ASP, etc.). Además, asegúrese de colocar un comentario en el campo de comentarios de MySQL para su bit_flags campo.

Encontrará estos sitios útiles al implementar este método:

Respondido el 22 de junio de 18 a las 17:06

Esto parece una forma espantosa de ofuscar la intención a los futuros programadores. Seguro que parece un gran problema guardar 7 bytes (¡asumiendo que está usando los 8 bools en esa única tabla!) -

@yep ¡no hay ofuscación en absoluto! Escribir documentación y MySQL comentarios explicando cada campo en la tabla (como se menciona en la respuesta). La estrategia de desenmascaramiento de MySQL sugerida parece sólida y almacenar hasta 16 campos booleanos diferentes con solo un par de columnas es mejor que tener 16 de ellos en su lugar. Si es demasiado confuso usar la manipulación de bits y prefiere usar su lenguaje de secuencias de comandos web para obtener cada booleano, simplemente guárdelo como un VARCHAR y realice el procedimiento de desenmascaramiento en el código (tampoco necesita limitarlo a 8 campos) ... - CPHPython

Me cansé de intentar obtener ceros, NULLS y '' redondear con precisión un ciclo de valores PHP, MySql y POST, así que solo uso 'Sí' y 'No'.

Esto funciona perfectamente y no necesita un tratamiento especial que no sea obvio y fácil de hacer.

Respondido 03 ago 17, 14:08

Si realmente quisiera desperdiciar tanto espacio y comprometer el rendimiento, podría haber hecho al menos CHAR (1) con las opciones Y y N. - Me gustan los tacos

En la mayoría de las situaciones del mundo real, existe una diferencia real entre un "no" y una mera ausencia de información. Por ejemplo, es posible que desee tener una casilla de verificación marcada de forma predeterminada si un usuario todavía no ha dicho "no". Exactamente, ¿cuánto espacio crees que estás ahorrando y cuánto procesamiento haces cada vez que necesitas distinguir entre un falso y un NULL, si es que PUEDES distinguir? En un mundo de imágenes almacenadas y video digital, el ahorro de espacio es absolutamente irrelevante, pero la claridad y el procesamiento reducido son reales. - geoff kendall

Esta respuesta no es incorrecta porque funcionará y no es tan mala como la gente le da crédito. Para la mayoría de los proyectos (es decir, tamaños de tabla <1 mil filas) Las diferencias de rendimiento entre las soluciones proporcionadas serán despreciables. No me quejaré si mis consultas regresan en 7 vs 5 milisegundos ... Para ser justos, sin embargo, si sus tablas crecen en las filas de 10 mil o más, esta probablemente no sea la solución preferida. - Brad

+1 de mí por usar el tipo de datos ENUM. Personalmente prefiero esta notación: ENUM ('y', 'n'). Es compacto (solo un byte de longitud), intuitivo y atractivo como convención a nivel de aplicación para todos los indicadores booleanos. Puede usarlo directamente con campos de formulario HTML. por ejemplo con PHP: > Si > No - Vlado

Lol, esto me llamó la atención, pero tengo que decir que @GeoffKendall tiene razón. En muchos casos, no hay necesidad de un rendimiento óptimo y cualquier método que haga el trabajo por usted es el método correcto. - madmenio

Refiriéndose a este enlace Tipo de datos booleano en Mysql, de acuerdo con el uso de la aplicación, si se desea almacenar solo 0 o 1, el bit (1) es la mejor opción.

Respondido 13 Abr '17, 13:04

Eso es verdad BIT(1) solo permitirá un b'0' or b'1' valor a almacenar. El mayor problema con BIT tipo de datos es que varias bibliotecas cliente tienen una variedad de manejo inestable del tipo de datos. Verifique el comportamiento en varias herramientas SQL (SQLyog, TOAD for MySQL, SQL Developer), herramientas que realizan "ingeniería inversa" en modelos de bases de datos y varios clientes, como JDBC, PHP, Perl DBI, y para una buena medida, pruebe algunos marcos ORM ( Hibernate, Mybatis, JPA). En términos de facilidad de uso, compatibilidad de herramientas / marcos / soporte nativo, TINYINT(1) es el claro ganador. - spencer7593

Si. La finalización depende del marco que se esté considerando para la aplicación. Por ejemplo, el marco Phalcon de PHP no maneja el tipo de datos Bit - Vidz

Para el registro, MyBatis admite tanto BIT y TINYINT. Consulte la clase JdbcType de MyBatis, mybatis.org/mybatis-3/apidocs/reference/org/apache/ibatis/type/… - Suerte

@Vidz Le doy más uno por la mención de BIT (1), pero también señalaría a los desarrolladores que leen esto: conozca su idioma que estará en la capa de aplicación / capa de acceso a datos y conozca el soporte de sus bibliotecas. Actualmente estoy usando Java y BIT (1) es la opción recomendada en este momento para bibliotecas como Hybernate y el uso de JDBC. Aquí está la URL [Ver tabla 5.2]: dev.mysql.com/doc/conector-j/en/… - Zack Jansen

Dado que MySQL (8.0.16) y MariaDB (10.2.1) implementaron la restricción CHECK, ahora usaría

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

Solo podrás almacenar 0, 1 or NULL, así como valores que se pueden convertir a 0 or 1 sin errores como '1', 0x00, b'1' or TRUE/FALSE.

Si no desea permitir NULL, agregue el NOT NULL opción

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

Tenga en cuenta que prácticamente no hay diferencia si usa TINYINT, TINYINT(1) or TINYINT(123).

Si desea que su esquema sea compatible con versiones posteriores, también puede usar BOOL or BOOLEAN

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

db <> demostración de violín

contestado el 26 de mayo de 19 a las 18:05

¿qué pasa con enum (0, 1) - santiago arizti

@santiagoarizti ENUM (debe ser enum('0', '1') - nota: son cadenas) no es una buena idea. Existen demasiados problemas debido a cómo se almacena internamente y cómo se tratan los valores que no son cadenas. P.ej. 0 y FALSE no se puede almacenar. 1 y TRUE a las que has recomendado '0'. Y 2 se convierte en '1'. - Pablo Spiegel

La mejor respuesta ... para aquellos que usan MySQL 8+ - dolmen

Después de leer las respuestas aquí, decidí usar bit(1) y sí, de alguna manera es mejor en espacio / tiempo, PERO después de un tiempo cambié de opinión y nunca lo volveré a usar. Complicó mucho mi desarrollo al usar declaraciones preparadas, bibliotecas, etc. (php).

Desde entonces, siempre uso tinyint(1), parece lo suficientemente bueno.

Respondido el 26 de junio de 18 a las 11:06

¿Le importaría explicar de qué manera complicó su desarrollo? - chazy chaz

@ChazyChaz espera verdadero / falso en lugar de 1/0, a diferencia de otras bases de datos como SQL Server. Esto a veces puede llevar a situaciones extrañas en las que cree que lo está configurando como verdadero, pero en realidad no sucede. - maembé

Puede utilizar el tipo de datos BOOL, BOOLEAN para almacenar valores booleanos.

Estos tipos son sinónimos de TINYINT (1)

Sin embargo, el tipo de datos BIT (1) tiene más sentido para almacenar un valor booleano (ya sea verdadero [1] o falso [0]), pero es más fácil trabajar con TINYINT (1) cuando se generan los datos, se realizan consultas, etc. encendido y para lograr la interoperabilidad entre MySQL y otras bases de datos. También puedes consultar esta respuesta o hilo.

MySQL también convierte los tipos de datos BOOL, BOOLEAN a TINYINT (1).

Además, lea documentación

Respondido 26 Abr '20, 11:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.