¿Cómo puedo eliminar una base de datos en SQLite?

SQLite en Android: Estado y Tipos de Datos

Valoración: 4.65 (8992 votos)

SQLite ha sido durante mucho tiempo una piedra angular para el almacenamiento de datos local en aplicaciones móviles, particularmente en el ecosistema Android. Su naturaleza ligera y embebida lo convierte en una opción atractiva para gestionar datos directamente en el dispositivo del usuario. Sin embargo, con el paso del tiempo y la evolución de las tecnologías, surgen preguntas sobre su relevancia y si sigue siendo una opción viable o si ha quedado obsoleto.

Índice de Contenido

¿Está Obsoleto SQLite en Android? Aclarando la Confusión

La pregunta sobre la obsolescencia de SQLite a menudo surge de confusiones con tecnologías relacionadas pero distintas. La información proporcionada menciona que Google ha deprecado WebSQL, refiriéndose a él como SQLite. Es crucial entender que WebSQL fue una API de base de datos del lado del cliente para navegadores web que utilizaba SQLite como backend. La deprecación de WebSQL por parte de Google se refiere específicamente a su desuso en el contexto de los navegadores web, no a la biblioteca nativa de SQLite utilizada en el desarrollo de aplicaciones Android.

¿SQLite está obsoleto en Android?
Google ha dejado obsoleto SQlite , también conocido como WebSQL.

El motor de base de datos SQLite en sí mismo sigue siendo activamente mantenido y utilizado ampliamente en una variedad de aplicaciones, incluyendo sistemas operativos móviles como Android, navegadores web (donde no se usa WebSQL, sino que el navegador puede usar SQLite para almacenamiento interno) y muchas otras aplicaciones de escritorio y embebidas. Por lo tanto, la biblioteca SQLite en sí misma no está obsoleta.

El contexto en el que se mencionan las "advertencias de Google" y los "workarounds" en la información proporcionada parece estar más alineado con entornos de desarrollo web o híbridos que buscan reemplazar la funcionalidad de WebSQL deprecado o proporcionar acceso a SQLite en contextos donde el acceso nativo al sistema de archivos es limitado, como en un navegador a través de WebAssembly.

Workarounds para Contextos Específicos (Basados en la Información Provista)

La información detalla dos enfoques para superar ciertas limitaciones o para habilitar el uso de SQLite en escenarios específicos, como los que podrían verse afectados por la deprecación de WebSQL o limitaciones del entorno (ej. AppStudio, navegadores):

Workaround 1: Usando SQLite3 WASM con localStorage

Este enfoque implica compilar la biblioteca SQLite3 a WASM (WebAssembly), permitiendo que código C/C++ como el de SQLite se ejecute en un entorno JavaScript (como un navegador). La información sugiere usar esto con `localStorage` del navegador para persistir los datos.

Este método requiere una versión específica del entorno de desarrollo (AppStudio 9.0.4+). La clave aquí es que los datos se guardan en `localStorage` del navegador, que es un almacén clave-valor con ciertas limitaciones.

Para implementarlo, se especifica `localStorage` como el nombre de la base de datos al abrirla:

DB = SqlOpenDatabase("localStorage")

Esto se basa en un sistema de archivos virtual (VFS) llamado `kvvfs` que mapea las operaciones de archivo de SQLite a las operaciones de clave-valor de `localStorage`.

Características y Notas de este Workaround:

  • Persistencia: Los datos guardados en `localStorage` son persistentes entre ejecuciones.
  • Limpieza: Se introduce la función `DB.clearStorage()` para eliminar la base de datos almacenada en `localStorage`.
  • Tamaño: `DB.storageSize()` permite conocer el espacio ocupado en `localStorage`.
  • Compresión: La base de datos en `localStorage` puede acumular "basura". Se puede limpiar y comprimir usando `DB.clearStorage()` seguido de `DB.exec("VACUUM INTO 'file:local?vfs=kvvfs'")`.
  • Sincronicidad: La función `Sql` se vuelve síncrona, lo que significa que completa su ejecución antes de que se ejecute la siguiente instrucción. Esto puede requerir ajustes en el código que dependía de comportamiento asíncrono. Se proporciona un ejemplo de código corrigiendo el uso de `Sql` con callbacks para manejar el resultado.
  • Restricción de Comillas: No se permiten comillas dobles (") en las sentencias SQL para valores; deben usarse comillas simples ('). Por ejemplo, `...AND customer_type = "T"...` debe ser `...AND customer_type = 'T'...`.
  • Mensajes de Error: Pueden aparecer nuevos mensajes de error en la consola que, según la fuente, pueden ser ignorados.

Restricciones de este Workaround:

  • Límite de Tamaño: `localStorage` generalmente tiene un límite de 10 MB (en Chrome, según la fuente), lo que restringe el tamaño de la base de datos.
  • Base de Datos Única: Solo se puede tener una base de datos persistente en `localStorage`. Otras bases de datos se perderán al recargar la página.
  • Incompatibilidad: No se puede usar SQLite WASM y plugins de Cordova simultáneamente. Se sugiere usar WASM para aplicaciones de escritorio y plugins de Cordova para aplicaciones móviles (lo que refuerza que este workaround es para un contexto específico, no nativo móvil tradicional).
  • Tamaño de la Librería: Añade aproximadamente 1.4 MB al tamaño de la aplicación.
  • Entorno de Prueba: Funciona con "Start in Desktop Browser" pero no con "Deploy to Local Folder".

Este workaround, según la fuente, está en evolución y sujeto a cambios.

Workaround 2: Usando OPFS

El segundo enfoque mencionado es el uso de OPFS (Origin Private File System). Esta es una API más moderna en navegadores que permite a las aplicaciones web acceder a un sistema de archivos privado y optimizado para el rendimiento dentro del origen del sitio. A diferencia de `localStorage`, OPFS permite guardar la base de datos en un archivo real.

El principal beneficio de OPFS es que elimina las restricciones de tamaño y número de bases de datos impuestas por `localStorage`. Al guardar la base de datos en un archivo, se pueden manejar conjuntos de datos mucho más grandes.

Para examinar las bases de datos guardadas con OPFS, la información sugiere herramientas como OPFS Explorer (una extensión de navegador) y DB Browser for SQLite (una aplicación de escritorio independiente que puede abrir archivos `.sqlite`).

En resumen, la confusión sobre la obsolescencia de SQLite en Android a menudo proviene de la deprecación de WebSQL. SQLite como biblioteca sigue siendo relevante y estas "soluciones alternativas" presentadas en la información son para habilitar su uso en entornos web o híbridos que se vieron afectados por la deprecación de WebSQL o tienen limitaciones de acceso al sistema de archivos.

Tipos de Datos en SQLite

Un aspecto fundamental al trabajar con cualquier base de datos es comprender su sistema de tipos de datos. SQLite utiliza un sistema de tipos dinámicos, lo que lo diferencia de muchas otras bases de datos SQL tradicionales que usan tipado estático.

SQLite solo tiene cuatro tipos de datos primitivos principales:

  1. INTEGER: Se utiliza para almacenar valores enteros con signo. El tamaño del entero depende del valor, pudiendo ser de 1, 2, 3, 4, 6 u 8 bytes.
  2. REAL: Se utiliza para almacenar valores numéricos de punto flotante, representados como números de 8 bytes según el estándar IEEE flotante.
  3. TEXT: Se utiliza para almacenar cadenas de caracteres. SQLite soporta codificaciones como UTF-8, UTF-16BE o UTF-16LE.
  4. BLOB: Se utiliza para almacenar datos binarios exactamente como fueron introducidos.

Estas cuatro clases de almacenamiento son los únicos tipos de datos nativos que un valor puede tener en SQLite.

Sistema de Tipos Dinámicos y Afinidad de Tipos

En el sistema de tipos dinámicos de SQLite, el tipo de un valor está asociado al propio valor, no a la columna en la que se almacena. Esto significa que teóricamente puedes almacenar cualquier tipo de valor en cualquier columna, independientemente del nombre del tipo que uses al definir la columna (por ejemplo, podrías intentar guardar texto en una columna declarada como INTEGER).

¿Qué base de datos se usa en Android?
En Android hay varias posibilidades para trabajar con base de datos. Podemos utilizar un sistema embebido como SQLite o conectar de diversas formas a una bbdd externa, como MySQL.

Sin embargo, el nombre del tipo de columna sí afecta la afinidad de tipos de la columna. La afinidad de tipos es una sugerencia para el motor de base de datos sobre el tipo de almacenamiento preferido para los datos en esa columna. SQLite usa cinco afinidades de tipos:

  • TEXT Affinity: Columnas declaradas con nombres que contienen 'TEXT', 'CHAR', 'CLOB', o no especifican tipo.
  • NUMERIC Affinity: Columnas declaradas con nombres que contienen 'NUM', 'INT', 'REAL', 'DOUB', 'FLOA', 'DEC', 'BOOL', 'DATE', 'TIME'.
  • INTEGER Affinity: Un subtipo de NUMERIC, para columnas con nombres que contienen 'INT'.
  • REAL Affinity: Un subtipo de NUMERIC, para columnas con nombres que contienen 'REAL', 'DOUB', 'FLOA'.
  • BLOB Affinity: Columnas declaradas con nombres que contienen 'BLOB' o que no tienen ningún tipo especificado en absoluto.

Cuando intentas insertar un valor en una columna, SQLite intenta convertir el valor al tipo preferido de la columna (su afinidad). Por ejemplo, si insertas un string que parece un número ('123') en una columna con afinidad INTEGER, SQLite intentará convertirlo a un entero. Si insertas un número (123) en una columna con afinidad TEXT, lo convertirá a su representación textual.

La información proporcionada advierte que usar nombres de tipo de columna no estándar, como "STRING" (en lugar de TEXT), puede llevar a resultados inesperados porque la afinidad resultante podría no ser la esperada (por ejemplo, podría caer en NUMERIC affinity si contiene "INT" o "REAL" como subcadena, aunque "STRING" probablemente caería en TEXT affinity). Por ello, se recomienda encarecermente usar solo los cuatro nombres de tipo primitivos de SQLite (`INTEGER`, `REAL`, `TEXT`, `BLOB`) o tipos que claramente definan la afinidad deseada para evitar ambigüedades.

Mapeo de Tipos de Nivel Superior a Tipos Primitivos

Aunque SQLite solo tiene cuatro tipos primitivos, las aplicaciones y frameworks (como el ejemplo de .NET mencionado en la fuente, o las bibliotecas en Android como Room o la API nativa) manejan la conversión de tipos de datos más complejos (como Booleanos, Fechas, Decimales, GUIDs, etc.) a uno de los cuatro tipos primitivos para su almacenamiento. La forma exacta en que se realiza este mapeo puede variar ligeramente entre diferentes bibliotecas o lenguajes, pero los principios son similares.

Aquí hay un ejemplo de cómo algunos tipos lógicos o de frameworks podrían ser mapeados a los tipos primitivos de SQLite, basado en la información provista:

Tipo Lógico/FrameworkTipo Primitivo SQLite PreferidoNotas de Mapeo Comunes
BooleanoINTEGERGeneralmente almacenado como 0 (falso) o 1 (verdadero).
Byte[]BLOBIdeal para datos binarios sin interpretar.
CharTEXT o INTEGERPuede ser almacenado como un string de un carácter o como su valor numérico.
DateOnly
DateTime
DateTimeOffset
TEXT o REALComúnmente almacenados como TEXT (ej. "YYYY-MM-DD HH:MM:SS.SSS") o como REAL (valor de día Juliano o segundos desde la época).
DecimalTEXTA menudo almacenado como TEXT para preservar la precisión que los tipos REAL podrían perder.
Double
Single
REALNúmeros de punto flotante estándar.
GUIDTEXT o BLOBPuede ser almacenado como su representación textual o como un arreglo de bytes binarios.
Int16
Int32
Int64
SByte
UInt16
UInt32
UInt64
INTEGERSegún el tamaño del valor, se usan 1, 2, 3, 4, 6 u 8 bytes enteros.
StringTEXTEl tipo natural para almacenar cadenas de caracteres.
TimeOnly
TimeSpan
TEXT o REALPuede ser almacenado como TEXT ("HH:MM:SS.SSS") o como REAL (representando el tiempo en días o segundos fraccionados).

La información también menciona la posibilidad de leer ciertos tipos (.NET en su ejemplo) desde tipos primitivos alternativos. Por ejemplo, leer un valor de fecha/hora o intervalo de tiempo que fue almacenado como `REAL` (valor Juliano) de vuelta a un tipo de fecha/hora o `TimeSpan` en la aplicación. Esto subraya la flexibilidad del sistema de tipos dinámicos de SQLite y cómo las bibliotecas pueden manejar estas conversiones.

Es importante recordar que las facetas como la longitud máxima para TEXT o la precisión y escala para números decimales, aunque se pueden especificar en la declaración de la columna (ej. `VARCHAR(255)`), no son forzadas por el motor de base de datos de SQLite. La aplicación es responsable de validar y hacer cumplir estas restricciones si son necesarias.

Preguntas Frecuentes sobre SQLite en Android

¿La deprecación de WebSQL por Google significa que no puedo usar SQLite en mis aplicaciones Android nativas?

No. La deprecación de WebSQL se refiere a una API de navegador web. El uso de la biblioteca SQLite nativa en aplicaciones Android a través de las APIs proporcionadas por el SDK de Android (o bibliotecas como Room) no está deprecado por esta razón.

¿Cuáles son los tipos de datos fundamentales en SQLite?

SQLite tiene cuatro tipos de datos primitivos: INTEGER, REAL, TEXT y BLOB.

¿Puedo definir columnas con tipos como BOOLEAN, DATE o DECIMAL en SQLite?

Puedes usar esos nombres al definir columnas, y SQLite les asignará una afinidad de tipo (generalmente NUMERIC). Sin embargo, los valores reales se almacenarán usando uno de los cuatro tipos primitivos. Las bibliotecas que uses se encargarán de mapear tus tipos lógicos (como un booleano de Java/Kotlin) al tipo primitivo de SQLite (como INTEGER 0 o 1) y viceversa.

¿El tamaño de la base de datos SQLite en Android está limitado?

En aplicaciones Android nativas que acceden al sistema de archivos, el límite principal es el espacio de almacenamiento disponible en el dispositivo. Sin embargo, si estás utilizando workarounds como el de SQLite WASM con `localStorage` en un contexto de navegador/híbrido, sí existen límites significativos (ej. 10 MB para `localStorage`).

¿Qué es la afinidad de tipos en SQLite?

Es una sugerencia para el motor de SQLite, basada en el nombre del tipo de la columna, sobre cuál es el tipo de almacenamiento primitivo preferido para los datos en esa columna. Ayuda a SQLite a decidir cómo convertir los valores al insertarlos.

Conclusión

A pesar de la confusión generada por la deprecación de WebSQL, el motor de base de datos SQLite sigue siendo una tecnología relevante y ampliamente utilizada, especialmente en el desarrollo de aplicaciones móviles para Android. Las discusiones sobre workarounds como SQLite3 WASM con `localStorage` o OPFS se refieren a soluciones para contextos específicos (principalmente web o híbridos) afectados por la deprecación de WebSQL o limitaciones del entorno, no a una obsolescencia general de SQLite en Android nativo.

Comprender el sistema de tipos de datos de SQLite, basado en sus cuatro tipos primitivos (INTEGER, REAL, TEXT, BLOB) y su sistema de tipado dinámico con afinidad de tipos, es esencial para trabajar eficazmente con esta base de datos. Aunque puedes usar nombres de tipo de columna más descriptivos, es recomendable ceñirse a los nombres de los tipos primitivos para evitar comportamientos inesperados y confiar en las bibliotecas de acceso a datos para manejar el mapeo a tipos más complejos de tu lenguaje de programación.

Si quieres conocer otros artículos parecidos a SQLite en Android: Estado y Tipos de Datos puedes visitar la categoría Bases de datos.

Ivan

Soy un entusiasta de la tecnología con especialización en bases de datos, particularmente en MySQL. A través de mis tutoriales detallados, busco desmitificar los conceptos complejos y proporcionar soluciones prácticas a los desafíos cotidianos relacionados con la gestión de datos

Aprende mas sobre MySQL

Subir