android sqlite - ¿Qué tan flexibles/restrictivos son los tipos de columna SQLite?
android-sqlite (1)
Los tipos de columnas de SQLite son flexibles (dinámicos), principalmente, parece atender la adopción / adaptación de tipos de columnas rígidas utilizadas por otros sistemas de gestión de bases de datos.
¡Nota! este Asnwer NO recomienda el uso de tipos de columnas extraños y maravillosos.
1) En realidad, puede usar prácticamente cualquier nombre para un tipo de columna, sin embargo, existen algunas limitaciones.
2) El
tipo de columna es el segundo valor en la definición de la columna, por ejemplo,
CREATE TABLE table (columnname columntype .....,....)
, aunque puede omitirse intencionalmente o quizás sin darse cuenta
Nota ver
5a)
3)
La primera limitación es que
mycolumn
INTEGER PRIMARY KEY
o
mycolumn
INTEGER PRIMARY KEY AUTOINCREMENT
es un tipo de columna especial.
La columna es un alias para el
rowid
que es un identificador numérico único (
AUTOINCREMENT
impone una regla de que el
rowid
debe ser mayor que el último rowid usado para la tabla, por ejemplo, si una fila usa id (9223372036854775807), cualquier intento posterior de agregar un la fila dará como resultado un error SQLITE FULL
).
Aumento automático de SQLite
4) Otras limitaciones son que el tipo de columna no debe confundir el analizador SQLite. Por ejemplo, un tipo de columna de PRIMARY, TABLE, INDEX dará como resultado una excepción SQLite ( error de sintaxis (código 1) ), por ejemplo, cuando se usa un tipo de columna de INDEX, entonces:
android.database.sqlite.SQLiteException: near "INDEX": syntax error (code 1):
ocurre.
5)
Un tipo de columna no es obligatorio, por ejemplo
CREATE TABLE mytable (...,PRIMARY_COL,....
en cuyo caso un
PRAGMA TABLE_INFO(tablename)
no mostrará ningún tipo, por ejemplo (3rd Line).
08-08 07:56:23.391 13097-13097/? D/TBL_INFO: Col=cid Value=8
08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=name Value=PRIMARY_COL
08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=type Value=
08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=notnull Value=1
08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=dflt_value Value=null
08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=pk Value=0
5a)
En algunos casos, el analizador SQLite saltará a PALABRAS CLAVE válidas, p. Ej.
CREATE TABLE mytable (mycolumn NOT NULL,...
da como resultado que
NOT NULL
se utilice para indicar una columna
NOT NULL
y que el
tipo
se tome como
ningún tipo
(la tabla_info anterior era en realidad de tal uso).
6)
Un tipo no está limitado a una sola palabra, por ejemplo,
VARYING CHARACTER(255)
o
THE BIG BAD WOLF
se puede especificar como un tipo como se puede ver en este extracto de table_info: -
08-08 08:23:26.423 4799-4799/? D/ TBLINFO: Col=type Value=THE BIG BAD WOLF
¡La razón para usar tipos de columna no estándar en SQLite!
En resumen, no hay ninguna razón, como se indicó al principio, la flexibilidad de los tipos de columna parece ser principalmente para atender la fácil adaptación de SQL de otros sistemas de gestión de bases de datos.
Los tipos de columna tienen poco efecto ya que los datos se almacenarán de acuerdo con lo que SQLite determine como la clase de almacenamiento que se utilizará. Con la excepción de rowid (ver 3) arriba) cualquier columna puede contener valores de cualquier tipo.
Con la excepción de los datos almacenados como un Blob, que deben recuperarse usando el
cursor.getBlob
y ese cursor.getBlob no se pueden usar para datos no almacenados como BLOB (getBlob no falla con los datos almacenados como TEXT), puede mucho recuperar datos (todo no necesariamente útil) usando cualquiera de los
cursor.get????
métodos
Aquí hay algunos ejemplos:
Para una columna donde los datos son
long myINT = 556677888;
se agrega (a través de
cv1.put(columnanme,myINT)
por ejemplo,
cv1.put(columnanme,myINT)
);
Entonces :-
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: Column=INTEGER_COL<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS INT >>556677888<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS LONG >>556677888<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS STRING >>556677888<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS DOUBLE >>5.56677888E8<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS FLOAT >>5.566779E8<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS SHORT >>15104<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: Unable to handle with getBlob.
getShort no vuelve al valor almacenado, getBlob no puede obtener el valor almacenado.
Para
Double myREAL = 213456789.4528791134567890109643534276;
: -
08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes: Column=REAL_COL<<
08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes: VALUE AS INT >>213456789<<
08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes: VALUE AS LONG >>213456789<<
08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes: VALUE AS STRING >>2.13457e+08<<
08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes: VALUE AS DOUBLE >>2.134567894528791E8<<
08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes: VALUE AS FLOAT >>2.1345678E8<<
08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes: VALUE AS SHORT >>6037<<
08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes: Unable to handle with getBlob.
Para
String myTEXT = "The Lazy Quick Brown Fox Jumped Over the Fence or something like that.";
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: Column=TEXT_COL<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS INT >>0<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS LONG >>0<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS STRING >>The Lazy Quick Brown Fox Jumped Over the Fence or something like that.<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS DOUBLE >>0.0<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS FLOAT >>0.0<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS SHORT >>0<<
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: VALUE AS BLOB >>[B@2f9e811e<<
Y aquí hay un ejemplo bastante ridículo con un tipo de columna de
my_char_is_not_a_char_but_an_int
según
PRAGMA TABLE_INFO
: -
08-08 09:19:03.657 13575-13575/mjt.soqanda D/TBL_INFO: Col=cid Value=7
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ TBLINFO: Col=name Value=my_char_is_not_a_char_but_an_int_COL
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ TBLINFO: Col=type Value=my_char_is_not_a_char_but_an_int
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ TBLINFO: Col=notnull Value=0
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ TBLINFO: Col=dflt_value Value=null
08-08 09:19:03.657 13575-13575/mjt.soqanda D/ TBLINFO: Col=pk Value=0
Los resultados (almacenados según ''Doble'' arriba) son: -
08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes: Column=my_char_is_not_a_char_but_an_int_COL<<
08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes: VALUE AS INT >>213456789<<
08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes: VALUE AS LONG >>213456789<<
08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes: VALUE AS STRING >>2.13457e+08<<
08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes: VALUE AS DOUBLE >>2.134567894528791E8<<
08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes: VALUE AS FLOAT >>2.1345678E8<<
08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes: VALUE AS SHORT >>6037<<
08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes: Unable to handle with getBlob.
Lo anterior se basó en lo siguiente: - Tipos de datos en SQLite Versión 3 Declaraciones PRAGMA de Autoincremento SQLite
El código se probó / ejecutó en un dispositivo emulado GenyMotion con API22 compilado con una versión mínima de 14 y un objetivo de 26.
Recientemente ha habido cierto debate sobre la flexibilidad de los tipos de columna en SQLite. De ahí la pregunta: ¿Qué tan flexibles son los tipos de columna SQLite?
Un argumento fue que los tipos están restringidos a los cinco principales, a saber, TEXTO, NÚMERO, INTEGER, REAL y BLOB, y adicionalmente los tipos de columna nombrados en la documentación oficial, es decir:
INT, TINYINT, SMALLINT, MEDIUMINT, BIGINT, UNSIGNED BIG INT, INT2, INT8, CHARACTER(20), VARCHAR(255), VARYING CHARACTER(255), NCHAR(55), NATIVE CHARACTER(70), NVARCHAR(100), CLOB,
no datatype specified (BLOB)
, DOUBLE, DOUBLE PRECISION, FLOAT, DECIMAL(10,5), BOOLEAN, DATE & DATETIME
.
3.1.1. Ejemplos de nombres de afinidad
Otro argumento fue que la lista era una lista de ejemplos y que los tipos de columna son más flexibles con las 5 reglas (como se muestra a continuación) que se aplican prácticamente de manera universal.
3.1. Determinación de la afinidad de columna
La afinidad de una columna está determinada por el tipo declarado de la columna, de acuerdo con las siguientes reglas en el orden mostrado:
1) Si el tipo declarado contiene la cadena "INT", entonces se le asigna afinidad INTEGER.
2) Si el tipo declarado de la columna contiene cualquiera de las cadenas "CHAR", "CLOB" o "TEXT", entonces esa columna tiene afinidad TEXT. Observe que el tipo VARCHAR contiene la cadena "CHAR" y, por lo tanto, se le asigna afinidad TEXTO.
3) Si el tipo declarado para una columna contiene la cadena "BLOB" o si no se especifica ningún tipo, entonces la columna tiene BLOB de afinidad.
4) Si el tipo declarado para una columna contiene cualquiera de las cadenas "REAL", "FLOA" o "DOUB", entonces la columna tiene una afinidad REAL.
5) De lo contrario, la afinidad es NUMÉRICA.
Tenga en cuenta que el orden de las reglas para determinar la afinidad de columna es importante. Una columna cuyo tipo declarado es "CHARINT" coincidirá con las reglas 1 y 2, pero la primera regla tiene prioridad y, por lo tanto, la afinidad de la columna será INTEGER.
3.1. Determinación de la afinidad de columna
Entonces, ¿cuáles son las entradas y salidas / derechos y errores de los tipos de columna SQLite?