MySQL Bool: TinyInt oder Enum?

tobias1985

Der Erlöser
ID: 37913
L
24 April 2006
4.963
607
Hallo zusammen,
ich bin gerade auf etwas gestoßen, wozu ich gerne eure Meinung hören würde. :)

In MySQL gibt es ja bekanntlich keinen Datentyp BOOL.
Bzw. der Datentyp wurde mittlerweile eingeführt, wird intern aber als TINYINT(1) verwendet, da eine korrekte Implementierung noch nicht vorgenommen wurde.

Es geht um ein Feld, das angibt, ob ein User gesperrt ist. Es gibt also nur 2 Werte. Normalerweise:
gesperrt = true
gesperrt = false

Was macht nun Sinn? Datentyp BOOL gibt es ja wie gesagt nicht. (zur Info, falls es jemanden interessiert: Stellt man BOOL in PHPMyAdmin ein, wird das Feld automatisch als TINYINT(1) angelegt)

Ist es besser, wenn ich TINYINT(1) einstelle?

Oder soll ich ein ENUM mit den zweit Werten 0 und 1 anlegen? (angeblich schneller als TINYINT, allerdings spielt die Geschwindigkeit für dieses Feld nicht wirklich eine Rolle. Wird ja nicht wirklich häufig aktualisiert bzw. ausgelesen)

Was würdet ihr machen?

Dass es kein BOOL als Datentyp gibt, echt unglaublich, aber wahr. *g*
 
Wenn du ENUM verwendest könntest du entweder true/false oder 1/0 zurückgeben lassen. Bei TINYINT(1) hättest du nur die 1 oder 0.

Code:
enum('false', 'true')

SELECT bool FROM table //'true' oder 'false'

SELECT bool+0 FROM table //1 oder 0

Edit: Klappt nicht mehr...
 
Zuletzt bearbeitet:
Also mir wäre ein Typumwandlung ala:
PHP:
$bool = (bool) $result; // 1 oder 0
dreimal lieber als:
PHP:
$bool = (bool) $result; // string 'true' oder string 'false'

Habe es noch nicht getestet, würde aber fast vermuten das bei letzterem true rauskommt weil es net leer ist. Ich habe bisher immer Tinyint verwendet und bilde mit ein das es mal irgendwo so empfohlen wurde.
 
Code:
enum('false', 'true')

SELECT bool FROM table //'true' oder 'false'

SELECT bool+0 FROM table //1 oder 0

Wenn ich zu 'false' 0 addiere, erhalte ich 0? Wenn ich zu 'true' 0 addiere, erhalte ich 1? Interessante Logik. Funktioniert so aber mit an Sicherheit grenzender Wahrscheinlichkeit nicht (zumindest ist mir kein Sonderfall der String->Integer-Konvertierung bekannt, der dieses Ergebnis plausibel erscheinen ließe).

Ich verwende immer TinyInts, wenn es nur zwei mögliche Zustände für das Feld gibt. Ein enum-Feld dürfte ja doch einen gewissen Overhead haben (Umwandlung der internen Notation in den String, den der User gespeichert hat).

Greetz

paddya
 
Nimm einen Tinyint und zähle darin die Zeiteinheiten (Tage, Wochen) der Sperre. Dann einfach regelmäßig runterzähle und schwupps sind die User automatisch nach Ablauf der Sperre wieder freigeschaltet. Für Dauersperren nimm einfach den maximal möglichen Wert...;)
 
@dubberle: Danke für die Idee. :D Kann ich zwar für dieses Projekt nicht brauchen, aber für das Nächste.

Bisher sind die Meisten wohl für TINYINT(1). :biggrin:
 
Ist es besser, wenn ich TINYINT(1) einstelle?

Oder soll ich ein ENUM mit den zweit Werten 0 und 1 anlegen? (angeblich schneller als TINYINT, allerdings spielt die Geschwindigkeit für dieses Feld nicht wirklich eine Rolle. Wird ja nicht wirklich häufig aktualisiert bzw. ausgelesen)
Geschwindgkeit müsste bei beiden auch gleich sein, da beide ihre Information in 8Bit speichern.


Also ich bin ganz klar für Enum, denn wenn man in MySQL noch den Strict Mode aktiviert schmeisst MySQL einen Fehler, wenn du in ein Enum-Feld andere Daten speichern willst, als wofür dieses Feld defineirt wurde. Tinyint kann immernoch 255 andere Werte annehmen :arrow: potentielle Fehlerquelle

Edit: Seit MySQL 5.0 gibt es noch den Datentyp Bit(1) ;) (ist aber auf Grund der internene Darstellung keine gute Idee)

Edit2: Es würde noch die Option Char(0) Null geben, ich weiß aber gerade echt nicht welche Performance-Impacts diese komische Darstellung haben kann :biggrin:

ich bleibe bei ENUM
 
Zuletzt bearbeitet:
Wenn ich zu 'false' 0 addiere, erhalte ich 0? Wenn ich zu 'true' 0 addiere, erhalte ich 1? Interessante Logik. Funktioniert so aber mit an Sicherheit grenzender Wahrscheinlichkeit nicht (zumindest ist mir kein Sonderfall der String->Integer-Konvertierung bekannt, der dieses Ergebnis plausibel erscheinen ließe).

erfasst :biggrin:
wenn du eine Zahl auf einen ENUM-Wert draufaddierst erhälst du den binären Wert unter dem der Wert in der DB abgelegt wurde.
Der Wert false wird mit der Bitfolge die im Dezimalsystem eine 0 repräsentiert abgelegt (0+0=0) und der Wert true mit der Bitfolge, die eine 1 ergibt (1+0=0).

Ich möchte aber nochmal anmerken, das solche Addierungstricks wirklich Dirty sind, wenn man ENUM nutzt sollte man es mit dem in der Datenbank hinterlegten Wert vergleichen, also:
PHP:
$status => $db->fetchOne('SELECT status FROM user WHERE id = ?', 93395);
if($status == 'gesperrt') {}
else {}
 
erfasst :biggrin:
wenn du eine Zahl auf einen ENUM-Wert draufaddierst erhälst du den binären Wert unter dem der Wert in der DB abgelegt wurde.
Der Wert false wird mit der Bitfolge die im Dezimalsystem eine 0 repräsentiert abgelegt (0+0=0) und der Wert true mit der Bitfolge, die eine 1 ergibt (1+0=0).

Ah, interessant. Das wusste ich noch nicht :)
Allerdings kann eine Lösung, deren Funktion davon abhängt, in welcher Reihenfolge man die Feldwerte bei der Erstellung der Tabelle übergibt, nicht wirklich produktiv nutzbar sein...

Greetz

paddya
 
Also ich hab' enums auch extrem gerne, einfach weil es semantisch korrekter ist.

Der einzige Grund fuer mich so boolean options als integers zu speichern waere mehrere optionen in ein Feld zu speichern (siehe Thread https://www.klamm.de/forum/showthread.php?t=288740).

Vom speed her kann ich mit ziemlicher sicherheit sagen dass es kaum einen unterschied macht, weil im Fall von einem enum einfach nur ein hashmap und ein array lookup dazu kommt fuer die uebersetzung von string->integer (vor query execution) und dann integer->string (result return).