Qué tipo de datos MySQL usar para almacenar valores booleanos
Frecuentes
Visto 898,553 veces
1262
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?
13 Respuestas
1273
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
259
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
75
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
36
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 comoCHAR(0)
NULL
ocupa solo un bit y puede tomar solo los valoresNULL
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
33
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
18
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
18
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
12
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!) - Sí
@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
EL BIT
existe el tipo. Ver dev.mysql.com/doc/refman/8.0/en/bit-type.html - dolmen
10
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
6
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
6
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))
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
3
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é
1
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 mysql boolean sqldatatypes or haz tu propia pregunta.
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 - smp7d
Pregunta relacionada con ¿Alternativa a muchos booleanos en MySQL? - tereško
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 - DevT
bit(1)
es un poco ** para importar en Excel. Cambiar atinyint(1)
obras. - Cees Timmermanahora tenemos booleano después de 5 años - V-SHY