Know How SQLITE

Dinge, die ich mir in SQLite3 nie merken kann (oft im Gegensatz zu SQLite2):

Datentypen

  • TEXT: NULL, TEXT, BLOB
  • NUMERIC: NULL, INTEGER, REAL, TEXT, BLOB
  • INTEGER: NULL, INTEGER, TEXT, BLOB
  • REAL: NULL, REAL, TEXT, BLOB
  • NONE: Keine Preferenz, die Spalte wird gespeichert wie sie abgelegt wurde.
Intern wird die Spalte wie folgt typisiert. Typen sind beim Vegleich ziemlich unverträglich, d. h. wenn man eine INTEGER mit einem BLOB vergleicht geht das eigentlich immer schief, selbst wenn der BLOB einen Integer-Wert enthält:

  • NULL, INTEGER, REAL, TEXT, BLOB
Deshalb ist es ab SQLite3 (im Gegensatz zu SQLite2) wichtig, die Spalten richtig zu definieren und ganz korrekt zu befüllen.

Alles, was kein einfacher String ist (ich habe noch keine Regel dafür) ist ein BLOB. Wenn man also einen gebundenen Parameter in eine NONE-Spalte speichert, kommt gar nicht selten ein BLOB heraus, und ein Vergleich a la ='Wert' funktioniert dann später nicht! Besser ist also, man speichert explizit einen String, indem man diesen konkateniert, also so (Integer und String die evtl. von einer Datei eingelesen wurden, also sonst zu einem BLOB würden):
INSERT INTO table VALUES ( 0+?, ''&? )
Das Fatale daran ist, dass es bei einfachen Tests funktioniert, also wenn man z. B. 0 und A reinspeichert wird das zu INTEGER und STRING, aber sobald man eine große Zahl oder einen Pfadname speichert ohne diese zu kalulieren, dann werden das plötzlich beides BLOBs, das hat mich schon Stunden Debugging gekostet, warum ein "prepared Statemetn" von C aus nicht funktioniert wie geplant. (Man muss das als gravierenden Fehler in SQLite3 ansehen, so wie in Oracle der Leerstring ein NULL-Value ist!)

ROWID

Jede Tabelle hat einen INTEGER PRIMARY KEY, dieser ist als ROWID, OID oder ROWID erreichbar. Definiert man diese Spalte selber (evtl. mit AUTOINCREMENT), dann wird diese Spalte verwendet, ansonsten wird eine intern erzeugt (es ist die ID im B-Tree).