Anda di halaman 1dari 39

1

Unidad 7 SQLite


QU ES UNA BASE DE DATOS?


Una base de datos es una coleccin de datos relacionados. Por dato se entiende a un hecho conocido que
puede ser almacenado y que posee un significado implcito.


Por ejemplo, considere los nombres, nmeros de telfono y direcciones de un conjunto de personas
almacenadas en una libreta de direcciones o en una computadora personal. Esto es una coleccin de datos
relacionados con un significado implcito, de esta forma, es una base de datos.


La definicin precedente es genrica, sin embargo, el uso comn del trmino base de datos es usualmente
ms restringido.


Una base de datos posee las siguientes propiedades implcitas:





En resumen, una base de datos posee alguna fuente a partir de la cual se derivan los datos, algn grado de
interaccin con el mundo real, y una audiencia que est activamente interesada en los contenidos de la
base de datos.


Un Sistema de Gestin de Base de Datos
(DBMS Database Management System) es
una coleccin de programas de software que
permite crear y mantener una base de datos.


De esta forma, el DBMS es un sistema de
software de propsito general que facilita el
proceso de definir, construir y manipular bases
de datos para diferentes aplicaciones.
2


Unidad 7 SQLite

Definir una base de datos consiste de especificar los tipos de datos, estructuras y restricciones para los
datos que sern almacenados en la base de datos.


Construir la base de datos es el proceso de almacenar los datos propiamente dichos en un medio de
almacenamiento controlado por el DBMS. Manipular una base de datos incluye funciones tales como:
consultar la base de datos para recuperar datos especficos, actualizar la base de datos para reflejar
cambios ocurridos en el mundo real, y generar reportes a partir de los datos.


No es necesario utilizar un software DBMS de propsito general para implementar
una base de datos computarizada. Uno podra escribir su propio conjunto de
programas para crear y mantener la base de datos, en efecto, creando su propio
software DBMS de propsito general. En cualquier caso, ya sea que se utilice un
DBMS de propsito general o no, usualmente se emplea una considerable cantidad
de software para manipular la base de datos.


La base de datos propiamente dicha ms el software DBMS conforma un Sistema de Base de Datos


Un DBMS proporciona un entorno conveniente y eficiente para ser utilizado al extraer y almacenar
informacin en la base de datos. Un sistema de bases de datos proporciona a los usuarios una vista
abstracta de los datos ocultando ciertos detalles de cmo se almacenan y mantienen los datos. Oracle 11g
es un software DBMS de propsito general.



3


Unidad 7 SQLite


DESCRIPCIN DE RDBMS Y ORDBMS


Michael Stonebraker, en el paper "Object-Relational DBMS: The Next Wave," clasifica a las aplicaciones de
bases de datos en cuatro tipos: datos simples sin consulta, datos simples con consulta, datos complejos sin
consulta, y datos complejos con consultas. Estos cuatro tipos describen sistemas de archivos, DBMSs
relacionales, DBMS orientados a objeto, y DBMSs objeto relacionales, respectivamente.




Una base de datos relacional est compuesta de muchas relaciones en la forma de tablas de dos
dimensiones compuestas por filas y columnas conteniendo tuplas (o registros) relacionadas.


Los tipos de consultas que atienden un sistema de gestin de base de datos relacional ( RDBMS ) varan
desde simples consultas incluyendo una nica tabla de base a consultas complicadas de mltiples tablas
incluyendo uniones, anidamiento, diferencia o unin de conjuntos, y otras. Oracle 11g es un RDBMS que
implementa todas las caractersticas relacionales ms funcionalidades enriquecidas, como ser: commits
rpidos, backup y recuperacin, conectividad escalable, bloque a nivel de filas, consistencia de lectura,
particionamiento de tablas, paralelizacin de consultas, bases de datos en clster, exportacin e
importacin de datos, entre otras.


La principal desventaja de bases de datos relacionales ocurre debido a su inhabilidad de manejar reas de
aplicacin como bases de datos espaciales, aplicaciones que manipulan imgenes, y otros tipos de
aplicaciones que incluyen la interrelacin compleja de datos.


La ambicin de representar objetos complejos ha provocado el desarrollo de sistemas orientados a objeto
incluyendo caractersticas de orientacin a objeto, tales como: tipos de dato abstractos y encapsulamiento
(la estructura internad de los datos es ocultada y las operaciones externas pueden ser invocadas sobre el
objeto especificado), herencia (tendiendo a la reutilizacin de definiciones existentes para crear nuevos
objetos), etc.
4


Unidad 7 SQLite

Una base de datos orientada a objetos emplea un modelo de datos que soporta caractersticas de
orientacin a objeto y tipos de datos abstractos. Bases de datos orientadas a objeto utilizan el podero de
los lenguajes de programacin orientados a objeto para proporcionar capacidades de programacin de
base de datos. Un sistema de gestin de base datos orientado a objetos ( OODBMS ) implementa un
modelo de objeto, estandarizado por ODMG (Object Database Management Group), que consiste de tipos
de dato, constructores de tipo, etc., similar al modelo estndar para bases de datos relacionales.


La principal desventaja de ODBMS es la mala performance en la manipulacin y acceso a datos. No como en
RDBMS, la optimizacin de consultas en OODBMS es altamente compleja. OODBMS tambin sufren
problemas de escalabilidad, y no son capaces de soportar sistemas de gran escala.


El principal objetivo de un ORDBMS es brindar los beneficios tanto del modelo relacional como del modelo
de objetos, tales como: escalabilidad y soporte de tipos de dato enriquecidos. ORDBMSs emplean un
modelo de datos que incorpora caractersticas de orientacin a objeto en RDBMSs. Toda la informacin es
almacenada en tablas, pero algunas de las entradas tabulares en la base de datos pueden poseer
estructuras de datos enriquecidas o complejas (tipos de dato abstractos). Un ORDBMS soporta una forma
extendida de SQL. Las extensiones son necesarias debido a que ORDBMS dan soporte a tipos de dato
abstractos.




NIVELES DE ABSTRACCIN DE DATOS


Una caracterstica fundamental de una base de datos es que la misma provee un nivel de abstraccin de
datos ocultando detalles acerca del almacenamiento de datos que no son necesarios para la mayora de los
usuarios de base de datos. Dicha abstraccin es provista a travs de un modelo de datos.
5


Unidad 7 SQLite

Un modelo de datos es una coleccin de conceptos que pueden ser utilizados para describir la estructura
de una base de datos. La estructura de una base de datos est conformada por los tipos de datos, las
relaciones entre los datos, y las restricciones que existen sobre los datos. La mayora de los modelos de
datos tambin incluyen un conjunto de operaciones bsicas para especificar recuperaciones y
actualizaciones realizadas sobre la base de datos.




EL MODELO ENTIDAD RELACIN


El modelo entidad relacin (ER) es un modelo de datos conceptual de alto nivel. Este modelo, y sus
extensiones, frecuentemente es utilizado para el diseo conceptual de aplicaciones de base de datos, y
muchas herramientas de diseo de base de datos emplean sus conceptos.


El modelo ER datos como entidades,
son relaciones entre entidades y
atributos. El objeto bsico que el
modelo ER representa es una entidad,
la cual es una cosa del mundo real
con existencia independiente. Una
entidad puede ser un objeto con
existencia fsica (una persona
determinada, un auto, una casa, un
empleado), o puede ser un objeto con
una existencia conceptual (una
compaa, un trabajo, un curso
universitario).


Unidad 7 SQLite

Cada entidad posee atributos; propiedades de inters que describen a la entidad. Por ejemplo, una entidad
empleado puede ser descrita por su apellido y nombre, edad, direccin, salario y tarea realizada. Una
entidad particular poseer un valor para cada uno de sus atributos Los valores de los atributos que
describen cada entidad se tornan la mayor parte de los datos que son almacenados en una base de datos.


Una base de datos normalmente contiene grupos de entidades que son similares. Por ejemplo, una
compaa que posee cientos de empleados puede desear almacenar informacin similar para cada uno de
sus empleados. Estas entidades empleado comparten el mismo conjunto de atributos, pero cada entidad
posee sus propios valores para cada atributo.


Un tipo entidad define una coleccin (o conjunto) de entidades que poseen los mismos atributos. Cada tipo
entidad en la base de datos es descrita por su nombre y atributos. La coleccin de todas las entidades de un
tipo entidad particular en la base de datos en un momento determinado es denominado conjunto de
entidades, usualmente citado por el mismo nombre del tipo entidad correspondiente. Por ejemplo,
EMPLEADO se refiere tanto a un tipo de entidad como al conjunto de todos los empleados almacenados en
la base de datos.





Una relacin entre dos o ms entidades representa una interaccin entre las entidades. Existen varias
relaciones implcitas entre tipos entidad. Una relacin existe cuando un atributo de un tipo entidad hace
referencia a otro tipo entidad. Por ejemplo, el atributo MANAGER del tipo entidad DEPARTMENT hace
referencia al empleado que gerencia el departamento en cuestin. Un tipo relacin entre tipos entidad
define un conjunto de asociaciones (conjunto de relaciones) entre entidades de esos tipos


Como ocurre con tipos entidad y conjuntos de entidades, un tipo relacin y su correspondiente conjunto de
relaciones son citados por el mismo nombre. Informalmente, cada relacin perteneciente al conjunto de
relaciones es una asociacin de entidades, donde la asociacin incluye una entidad de cada uno de los tipos
de entidades participantes.


6


Unidad 7 SQLite

Dichas relaciones instancias representan el hecho que las entidades participantes estn relacionadas en
alguna forma en el dominio de problema correspondiente. Por ejemplo, la relacin WORKS_FOR entre los
tipo entidad EMPLOYEE y DEPARTMENT asocia cada empleado con el departamento en el cual el mismo
trabaja.


EL MODELO DE DATOS RELACIONAL


El modelo de datos relacional utiliza el concepto de relacin matemtica, la cual puede representarse como
una tabla de valores como su bloque de construccin bsico. Dicho modelo se basa en la teora de
conjuntos y la lgica de predicados de primer orden, y sus principales caractersticas son la simplicidad y su
fundamentacin matemtica.


El modelo relacional representa la base de datos como una coleccin de relaciones, donde cada relacin se
asemeja a una tabla de valores o archivo plano de registros. Cuando una relacin es pensada como una
tabla de valores, cada fila en la tabla representa una coleccin de valores de datos relacionados.


En el modelo de datos relacional, cada fila en la tabla representa un hecho que corresponde a una entidad
o relacin en el mundo real. El nombre de la tabla y el nombre de las columnas son utilizados para facilitar
la interpretacin del significado de los valores en cada fila de la tabla.


Por ejemplo, la tabla EMPLOYEE es denominada de esta manera ya que cada fila representa hechos acerca
de una entidad empleado en particular. Los nombres de columnas especifican cmo interpretar los valores
de datos en cada fila de acuerdo a la columna a la cual cada valor pertenece. Todos los valores en una
columna son del mismo tipo de dato.
















7
8


Unidad 7 SQLite





9


Unidad 7 SQLite


ELEMENTOS QUE COMPONEN UNA TABLA



Tabla: La tabla es la estructura de almacenamiento bsica en un Sistema de Administracin de Base de
Datos Relacional (RDBMS). Los datos de las tablas se almacenan en filas y columnas. Cada tabla se define
con un nombre de tabla que la identifica unvocamente y un conjunto de columnas. Una vez que se crea
una tabla, se le pueden insertar filas de datos vlidos. Las filas de las tablas pueden ser consultadas,
borradas o actualizadas.


Columna: Una columna representa un tipo de datos en una tabla (por ejemplo, el nombre del cliente en la
tabla Clientes). Una columna tambin puede ser referenciada como atributo. Cada columna tiene un
nombre de columna, un tipo de dato (tal como CHAR, DATE o NUMBER), y un ancho (que puede ser
predeterminado por el tipo de dato, como en el caso de DATE) o una escala y precisin (slo para el tipo de
dato NUMBER).Todos los valores de una columna determinada tienen el mismo tipo de datos, y stos estn
extrados de un conjunto de valores legales llamado el dominio de la columna. Las columnas de una tabla
estn dispuestas en un orden especfico de izquierda a derecha. Sin embargo, el orden de stas cuando se
almacenan datos no es significativo, pero puede ser especificado cuando se los recupera.


Fila: Una fila es una combinacin de valores de columnas de una tabla (por ejemplo, la informacin acerca
de un cliente en la tabla Clientes). Una fila a menudo se denomina tupla o registro. Cada tabla tiene
cero o ms filas, conteniendo cada una un nico valor en cada columna. Las filas estn desordenadas; por
defecto, los datos estn dispuestos de acuerdo a cmo se insertaron.
10


Unidad 7 SQLite

Campo: Un campo se encuentra en la interseccin de una fila y una columna. El campo puede contener
datos. Si no hay datos en el campo, se dice que contiene un valor nulo. Los valores de los campos no se
pueden descomponer en componentes ms pequeos.


Clave primaria: Una clave primaria es una columna o conjunto de columnas que identifican unvocamente
cada fila de una tabla (por ejemplo, un nmero de cliente). Una tabla tiene una nica clave primaria y debe
contener un valor.


Clave fornea: Una clave fornea es una columna o conjunto de columnas que se refieren a una clave
primaria de la misma tabla o de otra. Se crean estas claves para reforzar las reglas de diseo de la base de
datos relacional. Una tabla puede contener ms de una clave fornea. Una combinacin clave
primaria/clave fornea crea una relacin padre/hijo entre las tablas que las contienen.








































TIPOS DE SENTENCIAS SQL


Las sentencias SQL se dividen en las siguientes categoras:


Sentencias de Lenguaje de Definicin de Datos (DDL Data Definition Language): crean,
modifican y eliminan objetos de la base de datos (por ejemplo: CREATE, ALTER, DROP, RENAME).
11


Unidad 7 SQLite

Sentencias de Lenguaje de Manipulacin de Datos (DML Data Manipulation Language):
insertan, modifican, eliminan y consultan filas de tablas de la base de datos (INSERT, UPDATE,
DELETE, SELECT).


Sentencias de Lenguaje de Control de Datos (DCL Data Control Language): permiten dar o
restringir derechos de acceso a la base de datos y a objetos especficos dentro de la base de datos
(GRANT, REVOKE).


Sentencias de Control de Transacciones: manejan los cambios hechos por los comandos del
lenguaje de manipulacin de datos. Los cambios a los datos pueden ser agrupados en
transacciones lgicas (COMMIT, ROLLBACK).


Sentencias de Control de Sesin: permiten que un usuario controle las propiedades de la sesin
corriente, incluyendo la posibilidad de habilitar o deshabilitar roles, y cambiar la configuracin del
lenguaje (ALTER SESSION, SET ROLE).


Sentencias de Control de Sistema: cambian las propiedades de una instancia de Oracle 11g.
Permiten cambiar diferentes parmetros de configuracin, tal como el nmero mnimo de
servidores compartidos, matar una sesin determinada y ejecutar otras tareas (ALTER SYSTEM,
ALTER SESSION, etc.).


Sentencias de SQL embebido: permite la incorporacin de sentencias DDL, DML y de control de
transacciones en un programa escrito en lenguaje procedural (OPEN, CLOSE, FETCH, EXECUTE, etc.).



12


Unidad 7 SQLite


Qu es una Base de Datos Embebida?


Una Base de Datos Embebida o Empotrada es aquella que NO inicia un servicio en nuestra mquina, es
independiente de la aplicacin, pudindose enlazar directamente a nuestro cdigo fuente o bien utilizarse
en forma de librera. Se utiliza normalmente en tres reas: en dispositivos mviles (por ejemplo: celulares,
PDAs), en sistemas de tiempo real y en aplicaciones de Internet donde el usuario no se relaciona con la
base de datos subyacente de forma directa.


Normalmente las bases de datos embebidas comparten una serie de caractersticas comunes:
Su pequeo tamao.
"Small footprint", en trminos de tamao de cdigo aadido a nuestra aplicacin.
Recursos que consumen.


Estas bases de datos pueden estar contenidas exclusivamente en memoria (y al cerrar la aplicacin, las
tablas se guardan en disco) o en disco, siendo en el primer caso mucho ms rpidas.


Ejemplos de DBMS embebidos: Berkeley DB de Oracle Corporation, EffiPRoz de EffiProz Systems, ElevateDB
de Elevate Software, Inc., Empress Embedded Database de Empress Software, Extensible Storage Engine de
Microsoft, eXtremeDB de McObject, Firebird Embedded, HSQLDB de HSQLDB.ORG, Informix Dynamic
Server (IDS) de IBM, InnoDB de Oracle Corporation, ITTIA DB de ITTIA, RDM Embedded and RDM Server de
Raima Inc., SolidDB de IBM, SQLite, SQL Server Compact de Microsoft Corporation, Valentina DB de
Paradigma Software, VistaDB de VistaDB Software, Inc., y Advantage_Database_Server de Sybase Inc.


13


Unidad 7 SQLite


QU ES SQLite?




SQLite es un sistema gestor de bases de datos
embebido, su creador es D. Richard Hipp, el cual
implementa una pequea librera de
aproximadamente 500kb, programado en el
lenguaje C, de dominio pblico, totalmente libre.


Uno de las primeras diferencia entre los motores de Bases de datos convencionales es su arquitectura
cliente/servidor, pues SQLite es independiente, simplemente se realizan llamadas a subrutinas o funciones
de las propias libreras de SQLite, lo cual reduce ampliamente la latencia en cuanto al acceso a las bases de
datos. Con lo cual podemos decir que las base de datos compuesta por la definicin de las tablas, ndices y
los propios datos son guardados por un solo archivo estndar y en una sola computadora.


La historia del proyecto SQLite


Cuando D. Richard Hipp trabajaba desarrollando software para la fuerza naval de los Estados Unidos,
comenz a desarrollar SQLite, segn l cuenta con sus propias palabras: El proyecto SQLite surgi de una
necesidad personal, para mi propio uso.


En enero de 2000 D. Richard Hipp estaba trabajando con su equipo de la General
Dynamics en la Fuerza naval de los Estados Unidos, en un proyecto de software, el
cual se conectaba a una base de datos Informix, el motor funcionaba muy bien,
pero haban tenido problemas para hacer una reconfiguracin cuando el sistema se
reiniciaba. Luego cambiaron a PostgreSQL, pero administrar la base de datos era un
poco ms compleja. Fue en ese momento cuando surgi la idea de escribir un
simple motor de base de datos SQL que permitiera leer los archivos del disco duro,
y luego ser llamados en diferentes solicitudes.
Cinco meses ms tarde comenz a escribir las primeras versiones de lo que hoy conocemos como SQLite,
con el pensamiento de que sera til en algn problema similar.


Es claro que SQLite tiene la capacidad de reemplazar a grandes motores de Bases de Datos y acoplarse al
desarrollo de nuestros proyectos informticos, ya sea en ambientes de prototipos de sistemas como as
tambin en complejos y robustos software.


Caractersticas


Tamao: SQLite tiene una pequea memoria y una nica biblioteca es necesaria para acceder a bases de
datos, lo que lo hace ideal para aplicaciones de bases de datos incorporadas.


Rendimiento de base de datos: SQLite realiza operaciones de manera eficiente y es ms rpido que MySQL
y PostgreSQL.
14


Unidad 7 SQLite

Estabilidad: SQLite es compatible con ACID, reunin de los cuatro criterios de Atomicidad, Consistencia,
Aislamiento y Durabilidad.


SQL: implementa un gran subconjunto de la ANSI 92 SQL estndar, incluyendo sub-consultas, generacin
de usuarios, vistas y triggers.


Interfaces: cuenta con diferentes interfaces del API, las cuales permiten trabajar con C++, PHP, Perl,
Python, Ruby, Tcl, Groovy, etc.


Costo: SQLite es de dominio pblico, y por tanto, es libre de utilizar para cualquier propsito sin costo y se
puede redistribuir libremente.


No posee configuracin: De la forma en que fue creado y diseado SQLite, NO necesita ser instalado. NO
prender, reiniciar o apagar un servidor, e incluso configurarlo. Esta cualidad permite que no haya un
administrador de base de datos para crear las tablas, vistas, asignar permisos. O bien la adopcin de
medidas de recuperacin de servidor por cada cada del sistema.


Portabilidad: SQLite puede ser ejecutado en diferentes sistemas operativos, como ser Windows, Linux,
BSD, Mac OS X, Solaris, HPUX,AIX o estar embebido en muchos otros como QNX, VxWorks, Symbian, Palm
OS, Windows CE. Se pude notar que muchos de ellos trabajan a 16, 32 y 64 Bits. La portabilidad no est
dada en s por el software, sino por la base de datos condensada en un solo fichero, que puede estar
situado en cualquier directorio, trayendo como ventaja que la base de datos puede ser fcilmente copiada
a algn dispositivo USB o ser enviada va correo electrnico.



15


Unidad 7 SQLite

Registros de longitud variable: Generalmente los motores asignan una cantidad fija de espacio en disco
para cada fila en la mayora de los campos de una determinada tabla. Por ejemplo, tomemos un campo de
tipo VARCHAR(255), esto significa que el motor le asignar 255 bytes de espacio fijo en disco,
independientemente de la cantidad de informacin que se almacene en ese campo. En cambio, SQLite
aplica su tecnologa y realizar todo lo contrario, utilizando para ello la cantidad de espacio en disco
necesario para almacenar la informacin real del campo. Tomando el ejemplo anterior, si quisiera
almacenar un solo carcter en un campo definido como VARCHAR(255), entonces un nico byte de espacio
de disco se consume. El uso de registros de longitud variable por SQLite, tiene una serie de ventajas, entre
ellas el resultado de un pequeo archivo de base de datos y optimizacin de la velocidad de la misma,
puesto que hay menos informacin desperdiciada que leer y recorrer.


As como encontramos algunas ventajas y caractersticas realmente asombrosas, tambin cuenta con
algunas limitaciones:


Limitaciones en Where: esta limitacin est dada por el soporte para clausulas anidadas.


Falta de Clave Fornea: se hace caso omiso de las claves forneas; esto quiere decir, cuando se realice la
creacin de la tabla desde el modo consola, est permitiendo el uso de la clausura, aunque no realizara el
chequeo de la misma.


Falta de documentacin en espaol: si bien ya contamos con una comunidad latino americana de SQLite,
sera importante encontrar mucha ms documentacin, libros, review, etc. como muchos otros motores de
bases de datos cuentan hoy en da.


Sintaxis SQL


Distincin entre maysculas y minsculas: las declaraciones SQL, incluidos los nombres de objetos,
no distinguen entre maysculas y minsculas. No obstante, las declaraciones SQL se suelen escribir
con palabras clave SQL en mayscula, por lo que seguiremos dicha convencin en este documento.
Aunque la sintaxis SQL no distingue entre maysculas y minsculas, los valores de texto literales s
lo hacen en SQL. Las operaciones de comparacin y ordenacin tambin distinguen entre
maysculas y minsculas, segn se haya especificado en la secuencia de intercalacin definida para
una columna o una operacin. Para obtener ms informacin, consulte COLLATE.


Espacio en blanco: debe usarse un carcter de espacio en blanco (por ejemplo, un espacio, una
tabulacin, un salto de lnea, etc.) para separar palabras independientes en una declaracin SQL.
Sin embargo, el espacio en blanco es optativo entre palabras y smbolos. El tipo y la cantidad de
caracteres de espacio en blanco en una declaracin SQL no es relevante. Puede utilizar espacios en
blanco (como la sangra o saltos de lnea) para dar un formato ms claro a las declaraciones SQL sin
que afecte a su funcionalidad.



Declaraciones de manipulacin y definicin de datos
16


Unidad 7 SQLite

Las declaraciones de manipulacin de datos son declaraciones SQL ms utilizadas. Estas declaraciones se
utilizan para recuperar, aadir y eliminar datos de las tablas de la base de datos. Se admiten las siguientes
declaraciones de manipulacin de datos.


SELECT


La declaracin SELECT se utiliza para consultar la base de datos. El resultado de una declaracin SELECT es
cero o ms filas de datos, donde cada fila tiene un nmero fijo de columnas. El nmero de columnas del
resultado se especifica mediante el nombre de la columna result o la lista de expresiones entre las palabras
clave SELECT y FROM (opcional).





sql-statement ::= SELECT [ALL | DISTINCT] result
[FROM table-list]
[WHERE expr]
[GROUP BY expr-list]
[HAVING expr]
[compound-op select-statement]*
[ORDER BY sort-expr-list]
[LIMIT integer [( OFFSET | , ) integer]]

result ::= result-column [, result-column]*

result-column ::= * | table-name . * | expr [[AS] string]

table-list ::= table [ join-op table join-args ]*

table ::= table-name [AS alias] |
( select ) [AS alias]

join-op ::= , | [NATURAL] [LEFT | RIGHT | FULL] [OUTER | INNER | CROSS]
JOIN

join-args ::= [ON expr] [USING ( id-list )]

compound-op ::= UNION | UNION ALL | INTERSECT | EXCEPT
sort-expr-list ::= expr [sort-order] [, expr [sort-order]]*
sort-order ::= [COLLATE collation-name] [ASC | DESC]
collation-name ::= BINARY | NOCASE
17


Unidad 7 SQLite

Cualquier expresin arbitraria se puede utilizar como resultado. Si una expresin del resultado es *, todas
las columnas de todas las tablas se reemplazan por dicha expresin. Si la expresin es el nombre de una
tabla seguido de .*, el resultado es todas las columnas de dicha tabla.


La palabra clave DISTINCT provoca la devolucin de un subconjunto de filas de resultados (donde cada fila
es distinta). Se asume que todos los valores de NULL son iguales. El comportamiento predeterminado es la
devolucin de todas las filas de resultados, que se pueden explicitar con la palabra clave ALL.


La consulta se ejecuta en una o varias tablas especificadas con la palabra clave FROM. Si los distintos
nombres de las tablas estn separados por comas, la consulta utiliza la unin cruzada de las distintas tablas.
La sintaxis de JOIN tambin se puede utilizar para especificar el modo de unin de las tablas. El nico tipo
de unin externa admitida es LEFT OUTER JOIN. La expresin de la clusula ON en join-args debe producir
como resultado un valor booleano. Se puede utilizar una subconsulta entre parntesis como una tabla de la
clusula FROM. Se puede omitir toda la clusula FROM, en cuyo caso, el resultado ser una nica fila con
los valores de la lista de expresiones result.


La clusula WHERE se utiliza para limitar el nmero de filas recuperadas por la consulta. Las expresiones de
la clusula WHERE deben producir como resultado un valor booleano. El filtrado de la clusula WHERE se
lleva a cabo antes de cualquier agrupacin, por lo que las expresiones de la clusula WHERE no pueden
incluir funciones de agregacin.


La clusula GROUP BY combina una o varias filas del resultado en una sola fila de resultados. La clusula
GROUP BY es especialmente til cuando el resultado contiene funciones de agregacin. Las expresiones de
la clusula GROUP BY no tienen por qu ser expresiones que aparezcan en la lista de expresiones SELECT.



18


Unidad 7 SQLite



La clusula HAVING se parece a WHERE, en el sentido que limita las filas devueltas por la declaracin. Sin
embargo, la clusula HAVING se aplica tras producirse cualquier agrupacin especificada por una clusula
GROUP BY. En consecuencia, la expresin HAVING puede hacer referencia a valores que incluyan funciones
de agregacin. No es necesario que aparezca ninguna expresin de la clusula HAVING en la lista SELECT. Al
igual que ocurre con la expresin WHERE, la expresin HAVING debe producir como resultado un valor
booleano.




La clusula ORDER BY provoca la ordenacin de las filas de resultados. El argumento sort-expr-list de la
clusula ORDER BY es una lista de expresiones utilizadas como clave para la ordenacin. Las expresiones no
tienen por qu formar parte del resultado de una declaracin SELECT, pero en una declaracin SELECT
compuesta (una declaracin SELECT que utilice uno de los operadores compound-op), cada expresin de
ordenacin debe coincidir exactamente con una de las columnas de resultados. Cada expresiones de
ordenacin puede ir acompaada, de forma opcional, de una clusula sort-order formada por la palabra
clave COLLATE y el nombre de la funcin de intercalacin utilizada para ordenar el texto, o bien la palabra
clave ASC o DESC para especificar el tipo de ordenacin (ascendente o descendente). sort-order se puede
omitir y utilizar el valor predeterminado (orden ascendente). Para obtener una definicin de la clusula
COLLATE y de las funciones de intercalacin, consulte COLLATE.


La clusula LIMIT pone un lmite superior al nmero de filas devueltas en el resultado. Un valor negativo de
LIMIT indica la ausencia de lmite superior. El OFFSET que sigue a LIMIT especifica el nmero de filas que se
deben saltar al principio del conjunto de resultados. En una consulta SELECT compuesta, la clusula LIMIT
tal vez aparezca slo tras la declaracin SELECT final. El lmite se aplica a toda la consulta. Tenga en cuenta
19


Unidad 7 SQLite

que si utiliza la palabra clave OFFSET en la clusula LIMIT, el lmite es el primer entero y el desfase es el
segundo entero. Si se utiliza una coma en vez de la palabra clave OFFSET, el desfase es primer nmero y el
lmite es el segundo. Esta aparente contradiccin es intencionada: maximiza la compatibilidad con sistemas
de bases de datos SQL heredados.


Un SELECT compuesto est formado por dos o ms declaraciones SELECT simples conectadas por uno de los
operadores UNION, UNION ALL, INTERSECT o EXCEPT. En un SELECT compuesto, todas las declaraciones
SELECT que lo forman deben especificar el mismo nmero de columnas de resultados. Slo puede haber
una clusula ORDER BY nica tras la declaracin SELECT final (y antes de la clusula LIMIT nica, si se ha
especificado). Los operadores UNION y UNION ALL combinan los resultados de las declaraciones SELECT
siguiente y anterior en una sola tabla. La diferencia reside en que en UNION, todas las filas de resultados
son distintas, mientras que en UNION ALL puede haber duplicados. El operador INTERSECT toma la
interseccin de los resultados de las declaraciones SELECT anterior y siguiente. EXCEPT toma el resultado
del SELECT anterior tras eliminar los resultados del SELECT siguiente. Si se conectan tres o ms
declaraciones SELECT en una compuesta, se agrupan de la primera a la ltima.





INSERT


La declaracin INSERT se expresa de dos formas bsicas y se utiliza para llenar tablas con datos.


sql-statement ::=

INSERT [OR conflict-algorithm] INTO [database-name.] table-name [(column-
list)] VALUES (value-list) |

INSERT [OR conflict-algorithm] INTO [database-name.] table-name [(column-
list)] select-statement

REPLACE INTO [database-name.] table-name [(column-list)] VALUES (value-
list) |

REPLACE INTO [database-name.] table-name [(column-list)] select-statement


La primera expresin (con la palabra clave VALUES) crea una nica nueva fila en una tabla existente. Si no
se especifica un column-list, el nmero de valores debe coincidir con el nmero de columnas de la tabla. Si
se especifica un column-list, el nmero de valores debe coincidir con el nmero de columnas especificadas.
20


Unidad 7 SQLite

Las columnas de la tabla que no aparecen en la lista de columnas se llenan con valores predeterminados en
el momento de creacin de la tabla, o con NULL si no hay ningn valore predeterminado definido.


La segunda expresin de la declaracin INSERT toma los datos de una declaracin SELECT. El nmero de
columnas del resultado de SELECT debe coincidir exactamente con el nmero de columnas de la tabla si no
se especifica column-list, o debe coincidir con el nmero de columnas especificadas en el column-list. Se
realiza una nueva entrada en la tabla por cada fila del resultado de SELECT. El SELECT puede ser simple o
compuesto. Para obtener una definicin de las declaraciones SELECT admitidas, consulte SELECT.


El conflict-algorithm opcional permite especificar un algoritmo de resolucin de conflictos de restricciones
alternativo y utilizarlo durante este comando. Para obtener una explicacin y una definicin de los
algoritmos de conflictos, consulte ON CONFLICT (algoritmos de conflictos).


Las dos formas de REPLACE INTO de la declaracin equivalen a utilizar la expresin INSERT [OR conflict-
algorithm] estndar con el algoritmo de conflictos REPLACE (es decir, el formulario INSERT OR REPLACE...).


UPDATE


La declaracin UPDATE se utiliza para cambiar el valor de las columnas de un conjunto de filas de una tabla.


sql-statement ::= UPDATE [OR conflict-algorithm] [database-name.] table-
name


SET assignment [, assignment]*



conflict-algorithm



::=
[WHERE expr]

ROLLBACK | ABORT | FAIL | IGNORE | REPLACE

assignment

::=

column-name = expr

Cada asignacin de un UPDATE especifica un nombre de columna a la izquierda del signo igual y una
expresin arbitraria a la derecha. La expresin puede utilizar los valores de otras columnas. Todas las
expresiones se calculan antes de realizar ninguna asignacin. Para obtener una definicin de las
expresiones permitidas, consulte Expresiones.


La clusula WHERE se utiliza para limitar las filas que se actualizan. La expresin de la clusula WHERE debe
producir como resultado un valor booleano.


El conflict-algorithm opcional permite especificar un algoritmo de resolucin de conflictos de restricciones
alternativo y utilizarlo durante este comando. Para obtener una explicacin y una definicin de los
algoritmos de conflictos, consulte ON CONFLICT (algoritmos de conflictos).


DELETE


El comando DELETE se utiliza para eliminar registros de una tabla.
21


Unidad 7 SQLite


sql-statement ::= DELETE FROM [database-name.] table-name [WHERE expr]


El comando est formado por las palabras clave DELETE FROM seguidas del nombre de la tabla de la que se
eliminarn los registros. Sin una clusula WHERE, se eliminan todas las filas de la tabla. Si se facilita una
clusula WHERE, slo se eliminan las filas que coincidan con la expresin. La expresin de la clusula
WHERE debe producir como resultado un valor booleano.


CREATE TABLE


Una declaracin CREATE TABLE est formada por las palabras clave CREATE TABLE, seguidas del nombre de
la nueva tabla y (entre parntesis) una lista de definiciones y restricciones de columnas. El nombre de la
tabla puede ser un identificador o una cadena.


sql-statement ::= CREATE [TEMP | TEMPORARY] TABLE [IF NOT EXISTS]
[database-name.] table-name
( column-def [, column-def]* [, constraint]* )

sql-statement ::= CREATE [TEMP | TEMPORARY] TABLE [database-name.] table-
name AS select-statement

column-def ::= name [type] [[CONSTRAINT name] column-constraint]*

type ::= typename | typename ( number ) | typename ( number ,
number )

column-constraint ::= NOT NULL [ conflict-clause ] |
PRIMARY KEY [sort-order] [ conflict-clause ]
[AUTOINCREMENT] |


UNIQUE [conflict-clause] |
CHECK ( expr ) |
DEFAULT default-value |
COLLATE collation-name

constraint ::= PRIMARY KEY ( column-list ) [conflict-clause] |
UNIQUE ( column-list ) [conflict-clause] |
CHECK ( expr )

conflict-clause ::= ON CONFLICT conflict-algorithm

conflict-algorithm ::= ROLLBACK | ABORT | FAIL | IGNORE | REPLACE

default-value ::= NULL | string | number | CURRENT_TIME | CURRENT_DATE |
CURRENT_TIMESTAMP

sort-order ::= ASC | DESC

collation-name ::= BINARY | NOCASE
22


Unidad 7 SQLite

Cada definicin de columna es el nombre de la columna seguido de su tipo de datos correspondiente y, por
ltimo, una o varias restricciones de columna opcionales. El tipo de datos de la columna limita los datos
que pueden guardarse en dicha columna. Si se intenta guardar un valor en una columna con tipos de datos
distintos, el motor de ejecucin convertir el valor en el tipo adecuado si es posible, o lanzar un error.
Consulte la seccin Compatibilidad de tipos de datos para obtener ms informacin.


La restriccin de la columna NOT NULL indica que la columna no puede contener valores NULL.


Una restriccin UNIQUE provoca la creacin de un ndice en la columna o columnas especificadas. Este
ndice puede contener claves nicas: dos filas no pueden contener valores duplicados o combinaciones de
valores para la columna o columnas especificadas. Una declaracin CREATE TABLE puede tener varias
restricciones UNIQUE, incluidas varias columnas con una restriccin UNIQUE en la definicin de la columna
o mltiples restricciones UNIQUE en el nivel de las tablas.


Una restriccin CHECK define una expresin que se calcula y debe ser true para poder insertar o actualizar
los datos de una fila. La expresin CHECK debe producir como resultado un valor booleano.


Una clusula COLLATE en una definicin de columna especifica qu funcin de intercalacin de texto debe
usarse al comparar entradas de texto en la columna. La funcin de intercalacin BINARY se utiliza de forma
predeterminada. Para obtener ms informacin sobre la clusula COLLATE y sus funciones de intercalacin,
consulte COLLATE.


La restriccin DEFAULT especifica un valor predeterminado para utilizarlo con un INSERT. El valor puede ser
NULL, una constante de cadena o un nmero. El valor predeterminado tambin puede ser una de las
palabras clave especiales (no distinguen entre maysculas y minsculas) CURRENT_TIME, CURRENT_DATE o
CURRENT_TIMESTAMP. Si el valor es NULL, se inserta (literalmente) una constante de cadena o un nmero
en la columna cada vez que una declaracin INSERT no especifique un valor para la columna. Si el valor es
CURRENT_TIME, CURRENT_DATE o CURRENT_TIMESTAMP, se inserta en la columna la fecha/hora UTC
actual. Para CURRENT_TIME, el formato es HH:MM:SS. Para CURRENT_DATE, el formato es YYYY-MM-DD.
El formato de CURRENT_TIMESTAMP es YYYY-MM-DD HH:MM:SS.


Al especificar un PRIMARY KEY, normalmente slo se crea un ndice de UNIQUE en la columna o columnas
correspondientes. Sin embargo, si la restriccin PRIMARY KEY se encuentra en una sola columna con el tipo
de datos INTEGER, dicha columna se puede utilizar internamente como clave principal real de la tabla. Esto
significa que la columna slo puede contener valores enteros nicos. Si una tabla no contiene una columna
INTEGER PRIMARY KEY, se generar automticamente una clave de enteros al insertar una fila. Siempre se
puede acceder a la clave principal de una fila mediante uno de los nombres especiales ROWID, OID o
_ROWID_. Puede utilizar estos nombres tanto si son un INTEGER PRIMARY KEY declarado explcitamente o
un valor interno generado. Una columna INTEGER PRIMARY KEY tambin puede contener la palabra clave
AUTOINCREMENT. Cuando se utiliza la palabra clave AUTOINCREMENT, la base de datos genera e inserta
automticamente una clave de enteros que aumenta secuencialmente en la columna INTEGER PRIMARY
KEY cuando se ejecuta una declaracin INSERT.
23


Unidad 7 SQLite

Slo puede haber una restriccin PRIMARY KEY en una declaracin CREATE TABLE. Puede ser parte de una
definicin de columna o tratarse de una restriccin PRIMARY KEY nica en el nivel de tablas. Una columna
de clave principal es NOT NULL implcitamente.


La clusula conflict-clause opcional con restricciones permite especificar un algoritmo de resolucin de
conflictos de restricciones alternativo predeterminado para dicha restriccin. El valor predeterminado es
ABORT. Las restricciones distintas de la misma tabla pueden tener distintos algoritmos de resolucin de
conflictos predeterminados. Si una declaracin INSERT o UPDATE especifica un algoritmo de resolucin de
conflictos de restricciones distinto, dicho algoritmo se utilizar en vez del especificado en la declaracin
CREATE TABLE. Consulte la seccin ON CONFLICT (algoritmos de conflictos) para obtener ms informacin.


Las restricciones adicionales, como las FOREIGN KEY, no producen errores porque el motor de ejecucin las
ignora.


Si las palabras clave TEMP o TEMPORARY se encuentran entre CREATE y TABLE, la tabla creada slo ser
visible dentro de la misma conexin de base de datos (instancia de SQLConnection). Se elimina
automticamente cuando se cierra la conexin de base de datos. Todos los ndices creados en una tabla
temporal tambin son temporales. Las tablas y los ndices temporales se guardan en un archivo
independiente distinto del archivo principal de la base de datos.


No hay lmites arbitrarios en el nmero de columnas o en el nmero de restricciones de una tabla.
Tampoco hay lmites arbitrarios en la cantidad de datos de una fila.


La expresin CREATE TABLE AS define la tabla como el conjunto de resultados de una consulta. Los
nombres de las columnas de la tabla son los nombres de las columnas del resultado.


Si la clusula IF NOT EXISTS opcional est presente y ya existe otra tabla con el mismo nombre, la base de
datos ignora el comando CREATE TABLE.


Se puede eliminar una tabla con la declaracin DROP TABLE, y se pueden realizar cambios limitados con la
declaracin ALTER TABLE.


ALTER TABLE


El comando ALTER TABLE permite al usuario renombrar o agregar una nueva columna a una tabla existente.
No es posible eliminar una columna de una tabla.


sql-statement ::= ALTER TABLE [database-name.] table-name alteration

alteration ::= RENAME TO new-table-name
alteration ::= ADD [COLUMN] column-def
24


Unidad 7 SQLite

Se utiliza la sintaxis RENAME TO para renombrar la tabla identificada por [database-name.] table-name
como new-table-name. Este comando no se puede utilizar para mover una tabla entre bases de datos
asociadas; slo sirve para renombrar una tabla dentro de la misma base de datos.


Si la tabla que se va a renombrar contiene activadores o ndices, stos permanecen asociados a la tabla una
vez renombrada. No obstante, si hay definiciones o declaraciones de vistas ejecutadas por activadores que
hacen referencia a la tabla que se est renombrando, no se actualizan automticamente con el nuevo
nombre de la tabla. Si la tabla renombrada tiene vistas o activadores asociados, debe descartarlos
manualmente y recrear las definiciones de los activadores o las vistas con el nuevo nombre de la tabla.


Se utiliza la sintaxis ADD [COLUMN] para agregar una nueva columna a una tabla existente. La nueva
columna siempre se aade al final de la lista de las columnas existentes. La clusula column-def puede
expresarse de todas las formas permitidas en una declaracin CREATE TABLE, aunque con las siguientes
restricciones:
La columna no puede tener una restriccin PRIMARY KEY o UNIQUE.
La columna no puede tener un valor predeterminado CURRENT_TIME, CURRENT_DATE o
CURRENT_TIMESTAMP.
Si se especifica una restriccin NOT NULL, la columna debe tener un valor predeterminado distinto
de NULL.


El tiempo de ejecucin de la declaracin ALTER TABLE no se ve afectado por la cantidad de datos de la
tabla.


DROP TABLE


La declaracin DROP TABLE elimina una tabla agregada con una declaracin CREATE TABLE. La tabla con el
table-name especificado es la que se descarta. Se elimina completamente de la base de datos y del archivo
del disco. No es posible recuperar la tabla. Todos los ndices asociados a la tabla se eliminan tambin.


sql-statement ::= DROP TABLE [IF EXISTS] [database-name.] table-name


De forma predeterminada, la declaracin DROP TABLE no reduce el tamao del archivo de base de datos. El
espacio libre de la base de datos se conserva y se utiliza en operaciones INSERT posteriores. Para eliminar
espacio libre de la base de datos, utilice el mtodo SQLConnection.clean(). Si el parmetro autoClean se
establece en true al crear la base de datos por primera vez, el espacio se libera automticamente.


La clusula IF EXISTS opcional desactiva el error que se producira si la tabla no existiese.


Compatibilidad de tipos de datos


Al contrario de lo que ocurre con la mayora de bases de datos SQL, el motor de base de datos SQLite no
exige que las columnas de las tablas contengan valores de tipos concretos. El motor de ejecucin utiliza dos
conceptos, las clases de almacenamiento y la afinidad de columnas, para controlar los tipos de datos. En
25


Unidad 7 SQLite

esta seccin se describen las clases de almacenamiento y la afinidad de columnas, as como el modo en que
se resuelven distintos tipos de datos en diversas condiciones:


Las clases de almacenamiento representan los tipos de datos reales que se utilizan para guardar valores en
una base de datos. Estn disponibles las siguientes clases de almacenamiento:


INTEGER: el valor es un entero con signo.
REAL: el valor es un valor de nmero de coma flotante.
TEXT: el valor es una cadena de texto.
BLOB: el valor es un objeto grande binario (BLOB); dicho de otro modo, datos binarios sin procesar.
NULL: el valor es un valor NULL.




Todos los valores suministrados a la base de datos como literales incorporados en una declaracin SQL o
valores ligados al uso de parmetros en una declaracin SQL preparada se asignan a una clase de
almacenamiento antes de que se ejecute la declaracin SQL.


A los literales que forman parte de una declaracin SQL se les asigna una clase de almacenamiento TEXT si
estn encerrados con comillas simples o dobles, una clase INTEGER si el literal est especificado como un
nmero sin comillas, sin punto decimal ni exponente, una clase REAL si el literal es un nmero sin comillas,
con punto decimal o exponente y una clase de almacenamiento NULL si el valor es NULL. Los literales con
clase de almacenamiento BLOB se especifican con la notacin X'ABCD'. Para obtener ms informacin,
consulte Valores literales en expresiones.
26


Unidad 7 SQLite


Nuestra primera base de datos. Creacin y Manipulacin


Para utilizar SQLite disponemos de los conocimientos generales sobre SQL. En nuestro ejemplo, pasaremos
directamente a crear una clase de ayuda de base de datos para la aplicacin. Creamos una clase de ayuda
para que los detalles relacionados con la creacin y actualizacin de la base de datos, de apertura y cierre
de conexiones, y de ejecucin de consultas se incluyan en un mismo punto y no se repitan en el cdigo de
la aplicacin.


De este modo, nuestras clases Activity y Service podrn utilizar sencillos mtodos get e insert, con objetos
especficos que representen el modelo, o Collections en lugar de abstracciones especficas de base de datos
(como el objeto Cursor de Android que representa un conjunto de resultados de consulta). Imagine que
esta clase es una Capa de Acceso de Datos (DAL) en miniatura.



public class DBHelper {

public static final String DEVICE_ALERT_ENABLED_ZIP = "DAEZ99";
public static final String DB_NAME = "w_alert";
public static final String DB_TABLE = "w_alert_loc";
public static final int DB_VERSION = 3;

private static final String CLASSNAME = DBHelper.class.getSimpleName();
private static final String[] COLS = new String[] { "_id", "zip", "city", "region",
"lastalert", "alertenabled" };

private SQLiteDatabase db;
private final DBOpenHelper dbOpenHelper;

//
// inner classes
//

public static class Location {

public long id;
public long lastalert;
public int alertenabled;
public String zip;
// include city and region because geocode is expensive
public String city;
public String region;

public Location() {
}

public Location(final long id, final long lastalert, final int alertenabled,
final String zip,
final String city, final String region) {
this.id = id;
this.lastalert = lastalert;
this.alertenabled = alertenabled;
this.zip = zip;
this.city = city;
this.region = region;
27


Unidad 7 SQLite


}

@Override
public String toString() {
return this.zip + " " + this.city + ", " + this.region;
}
}

private static class DBOpenHelper extends SQLiteOpenHelper {

private static final String DB_CREATE = "CREATE TABLE "
+ DBHelper.DB_TABLE
+ " (_id INTEGER PRIMARY KEY, zip TEXT UNIQUE NOT NULL, city TEXT, region
TEXT, lastalert INTEGER, alertenabled INTEGER);";

public DBOpenHelper(final Context context) {
super(context, DBHelper.DB_NAME, null, DBHelper.DB_VERSION);
}

@Override
public void onCreate(final SQLiteDatabase db) {
try {
db.execSQL(DBOpenHelper.DB_CREATE);
} catch (SQLException e) {
Log.e(Constants.LOGTAG, DBHelper.CLASSNAME, e);
}
}

@Override
public void onOpen(final SQLiteDatabase db) {
super.onOpen(db);
}

@Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int
newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + DBHelper.DB_TABLE);
onCreate(db);
}
}

//
// end inner classes
//

public DBHelper(final Context context) {
this.dbOpenHelper = new DBOpenHelper(context);
establishDb();
}

private void establishDb() {
if (this.db == null) {
this.db = this.dbOpenHelper.getWritableDatabase();
}
}

public void cleanup() {
if (this.db != null) {
this.db.close();
28


Unidad 7 SQLite


this.db = null;
}
}

public void insert(final Location location) {
ContentValues values = new ContentValues();
values.put("zip", location.zip);
values.put("city", location.city);
values.put("region", location.region);
values.put("lastalert", location.lastalert);
values.put("alertenabled", location.alertenabled);
this.db.insert(DBHelper.DB_TABLE, null, values);
}

public void update(final Location location) {
ContentValues values = new ContentValues();
values.put("zip", location.zip);
values.put("city", location.city);
values.put("region", location.region);
values.put("lastalert", location.lastalert);
values.put("alertenabled", location.alertenabled);
this.db.update(DBHelper.DB_TABLE, values, "_id=" + location.id, null);
}

public void delete(final long id) {
this.db.delete(DBHelper.DB_TABLE, "_id=" + id, null);
}

public void delete(final String zip) {
this.db.delete(DBHelper.DB_TABLE, "zip='" + zip + "'", null);
}

public Location get(final String zip) {
Cursor c = null;
Location location = null;
try {
c = this.db.query(true, DBHelper.DB_TABLE, DBHelper.COLS, "zip = '" + zip +
"'", null, null, null, null,
null);
if (c.getCount() > 0) {
c.moveToFirst();
location = new Location();
location.id = c.getLong(0);
location.zip = c.getString(1);
location.city = c.getString(2);
location.region = c.getString(3);
location.lastalert = c.getLong(4);
location.alertenabled = c.getInt(5);
}
} catch (SQLException e) {
Log.v(Constants.LOGTAG, DBHelper.CLASSNAME, e);
} finally {
if (c != null && !c.isClosed()) {
c.close();
}
}
return location;
}
29


Unidad 7 SQLite


public List<Location> getAll() {
ArrayList<Location> ret = new ArrayList<Location>();
Cursor c = null;
try {
c = this.db.query(DBHelper.DB_TABLE, DBHelper.COLS, null, null, null, null,
null);

int numRows = c.getCount();
c.moveToFirst();
for (int i = 0; i < numRows; ++i) {
Location location = new Location();
location.id = c.getLong(0);
location.zip = c.getString(1);
location.city = c.getString(2);
location.region = c.getString(3);
location.lastalert = c.getLong(4);
location.alertenabled = c.getInt(5);
// don't return special device alert enabled marker location in all list
if (!location.zip.equals(DBHelper.DEVICE_ALERT_ENABLED_ZIP)) {
ret.add(location);
}
c.moveToNext();
}
} catch (SQLException e) {
Log.v(Constants.LOGTAG, DBHelper.CLASSNAME, e);
} finally {
if (c != null && !c.isClosed()) {
c.close();
}
}
return ret;
}

public List<Location> getAllAlertEnabled() {
Cursor c = null;
ArrayList<Location> ret = new ArrayList<Location>();
try {
c = this.db.query(DBHelper.DB_TABLE, DBHelper.COLS, "alertenabled = 1", null,
null, null, null);
int numRows = c.getCount();
c.moveToFirst();
for (int i = 0; i < numRows; ++i) {
Location location = new Location();
location.id = c.getLong(0);
location.zip = c.getString(1);
location.city = c.getString(2);
location.region = c.getString(3);
location.lastalert = c.getLong(4);
location.alertenabled = c.getInt(5);
// don't return special device alert enabled marker location in all list
if (!location.zip.equals(DBHelper.DEVICE_ALERT_ENABLED_ZIP)) {
ret.add(location);
}
c.moveToNext();
}
} catch (SQLException e) {
Log.v(Constants.LOGTAG, DBHelper.CLASSNAME, e);
} finally {
if (c != null && !c.isClosed()) {
c.close();
30


Unidad 7 SQLite


}
}
return ret;
}
}



En la clase DBHelper tenemos varias constantes que definen importantes valores estticos relacionados con
la base de datos con la que queremos trabajar, como el nombre, la versin y un nombre de tabla.


La primera clase interna es un sencillo bean Location que se utiliza para representar la ubicacin
seleccionada por el usuario para guardar. Intencionadamente, esta clase carece de mecanismos de acceso y
mutadores, ya que aaden sobrecarga y no los necesitamos para la aplicacin (no la mostraremos).
La segunda clase interna es una implementacin SQLiteOpenHelper.


Nuestra clase interna DBOpenHelper ampla SQLiteOpenHelper, que es una clase proporcionada por
Android para ayudar a la creacin, actualizacin y apertura de bases de datos. En esta clase incluimos una
cadena que representa la consulta CREATE que utilizaremos para crear la tabla de la base de datos; muestra
las columnas exactas y los tipos que tendr nuestra tabla. Los tipos de datos empleados son muy sencillos:
utilizaremos principalmente INTEGER y TEXT (si necesita informacin adicional sobre otros tipos admitidos
por SQLite, consulte la documentacin en http://www.sqlite.org/datatype3.html).





Adems, en DBOpenHelper implementamos varios mtodos de retrollamada SQLiteOpenHelper, en
especial onCreate y onUpgrade (tambin se admite onOpen pero no lo utilizaremos). Explicaremos el
funcionamiento de estas retrollamadas y la utilidad de la clase en la segunda parte de DBHelper (la clase
externa).


Nuestra clase DBHelper contiene una referencia de variable miembro a un objeto SQLiteDatabase. Este
objeto es el motor de bases de datos de Android y se utiliza para abrir conexiones, ejecutar elementos SQL
y otras operaciones.


Tras ello, se crea una instancia de la clase interna DBOpenHelper en el constructor. Seguidamente, se utiliza
dbOpenHelper, dentro del mtodo establishDb si la referencia db es nuil, para invocar openDatabase con el
31


Unidad 7 SQLite

contexto, nombre y versin de la base de datos actuales. De este modo se establece db como instancia de
SQLiteDatabase a travs de DBOpenHelper.


Aunque puede abrir una conexin de base de datos directamente, el uso de open invoca las retrollamadas
proporcionadas y facilita el proceso. Con esta tcnica, al intentar abrir la conexin a la base de datos, se
crea o actualiza automticamente (o se devuelve), si es necesario, a travs de DBOpenHelper. Aunque el
uso de DBOpenHelper implica pasos adicionales, una vez aplicado resulta muy til para modificar la
estructura de tablas (basta con incrementar la versin y hacer lo necesario en la retrollamada onUp-grade;
sin esto, sera necesario modificar y/o eliminar manualmente y volver a crear la estructura existente). Otro
elemento importante que proporcionar en una clase de ayuda como sta es un mtodo cleanup. Lo utilizan
los invocadores para llamarlo cuando se detienen, para cerrar conexiones y liberar recursos.


Tras el mtodo cleanup vemos los mtodos SQL que encapsulan las operaciones proporcionadas por la
clase de ayuda. En esta clase contamos con mtodos para aadir, actualizar, eliminar y obtener datos.
Tambin tenemos los mtodos especializados get y get all, en los que vemos cmo se utiliza el objeto db
para ejecutar consultas. La clase SQLiteDatabase dispone de numerosos mtodos como insert, update y
delete, y proporciona acceso query directo que devuelve un Cursor sobre un conjunto de resultados.


Utilizando sqlite3


Al crear una base de datos para una aplicacin en Android, los archivos de la misma se crean en
/datos/datos/ [NOMBRE_PAQUETE] /base de datos/db.nombre. Estos archivos son SQLite, pero existe
una forma de manipular, volcar, restaurar y trabajar con bases de datos a travs de los mismos por medio
de la herramienta sqlite3.


Puedes acceder a esta herramienta a travs de la lnea de comandos si ejecuta los siguientes comandos


cd [ANDROID_HOME]/tools
adb shell
sqlite3 /ruta_donde_se_almaceno_la_base_de_datos


Una vez en la ventana de smbolo del sistema (con el signo #), puede ejecutar comandos sqlite3, como. help
para empezar.


Desde la herramienta puedes ejecutar comandos bsicos como SELECT o INSERT, u otros ms avanzados
para tablas como CREATE o ALTER. Esta herramienta resulta muy til para operaciones bsicas y de
resolucin de problemas, y para volcar y abrir datos (.dump y .load, respectivamente). Como otras
herramientas SQL de lnea de comandos, se necesita tiempo para familiarizarse con su formato pero no hay
mejor forma de crear copias de seguridad de los datos o abrirlos. (Si necesita estas funciones, en la mayora
de los casos el desarrollo para mviles no exige bases de datos de gran tamao. Recuerde que esta
herramienta slo est disponible a travs de la consola de desarrollo y no para abrir datos en una
aplicacin real).
32


Unidad 7 SQLite


ContentProvider y manipulacin de datos


Ahora que sabemos cmo utilizar la compatibilidad de Android con SQLite, para crear y acceder a tablas,
almacenar datos o investigar bases de datos con las herramientas proporcionadas por la consola, el
siguiente paso consiste en crear y utilizar ContentProvider, el ltimo aspecto de procesamiento de datos en
la plataforma.


En Android se utiliza ContentProvider para compartir datos entre aplicaciones. Ya hemos analizado el hecho
de que cada aplicacin se ejecuta en su propio proceso (normalmente) y que los archivos y datos que
almacena no son accesibles para otras aplicaciones de forma predeterminada. Tambin hemos explicado
cmo conseguir que preferencias y archivos estn disponibles entre aplicaciones gracias a los permisos
correctos y al contexto y ruta de cada aplicacin. No obstante, es una solucin limitada para aplicaciones
relacionadas que ya conocen sus correspondientes detalles. Por el contrario, con ContentProvider puede
publicar y mostrar un determinado tipo de datos que otras aplicaciones utilicen para consultar, aadir,
actualizar y eliminar, sin necesidad de que conozcan con antelacin las rutas o recursos, o quin
proporciona el contenido.


El ejemplo convencional de ContentProvider en Android es una lista de contactos, la lista de nombres,
direcciones y telfonos almacenada en el telfono. Puede acceder a estos datos desde cualquier aplicacin
si utiliza un URI concreto, content://con-tacts/people/, y una serie de mtodos proporcionados por las
clases Activity y ContentResolver para recuperar y almacenar datos. En un apartado posterior encontrar
ms informacin sobre ContentResolver. Otro concepto relacionado con datos de ContentProvider es
Cursor, el mismo objeto que utilizamos anteriormente para trabajar con conjuntos de resultados de bases
de datos SQLite. Cursor tambin lo devuelven los mtodos de consulta que veremos en breve.


En este apartado crearemos varias aplicaciones de ejemplo para ilustrar ContentProvider desde todos los
ngulos. Primero crearemos una aplicacin basa-da en una nica actividad, ProviderExplorer, que utiliza la
base de datos de contactos incorporada para consultar, aadir, actualizar y eliminar datos. Tras ello,
crearemos otra aplicacin que implementa su propio ContentProvider e incluye una actividad de tipo
explorador para manipular los datos. Adems, analizaremos otros proveedores incorporados de la
plataforma.


La aplicacin ProviderExplorer tendr una pantalla de gran tamao en la que podemos desplazarnos.
Recuerde que nos centraremos en una actividad, para mostrar todas las operaciones ContentProvider en el
mismo punto, en lugar de en aspectos estticos o de facilidad de uso (la aplicacin es intencionadamente
horrible, al menos esta vez).


Para comenzar, analizaremos la sintaxis de URI y las combinaciones y rutas utilizadas para realizar distintas
operaciones con las clases ContentProvider y ContentResolver.


Formas de representar las URI y manipulacin de registros


Todo ContentProvider debe mostrar un CONTENT_URI exclusivo que se utiliza para identificar el tipo de
contenido que procesa. Este URI se utiliza de dos formas para consultar los datos, singular o plural
33


Unidad 7 SQLite



URI DESCRIPCIN
cont ent : //contacta/peopl e/
Devuelve una lista (List) de todas las personas del proveedor
registrado para procesar content: //contacts

cont ent : / / cont act s/
peopl e/ 1
Devuelve o manipula una nica persona con el ID =1 del
proveedor registrado para procesar content: //contacts



El concepto de URI aparece independientemente de que consulte datos, los aada o elimine, como veremos en breve.
Para familiarizarnos con el proceso, veremos los mtodos bsicos de manipulacin de datos CRUD y su relacin con la
base de datos de contactos y sus respectivos URI.

Analizaremos cada tarea para destacar los detalles: crear, leer, actualizar y eliminar. Para hacerlo de forma concisa,
crearemos una nica actividad que se encarga de todas estas acciones en el ejemplo ProviderExplorer. En apartados
posteriores analizaremos distintas partes de la actividad para centrarnos en cada tarea.
Lo primero ser configurar la estructura del proveedor de contactos, en la primera parte del siguiente listado, el inicio
de la clase ProviderExplorer.


publ i c cl ass Pr ovi der Expl or er ext ends Act i vi t y {

pr i vat e Edi t Text addName;
pr i vat e Edi t Text addPhoneNumber ;
pr i vat e Edi t Text edi t Name;
pr i vat e Edi t Text edi t PhoneNumber ;
pr i vat e But t on addCont act ;
pr i vat e But t on edi t Cont act ;

pr i vat e l ong cont act I d;

pr i vat e cl ass Cont act {

publ i c l ong i d;
publ i c St r i ng name;
publ i c St r i ng phoneNumber ;

publ i c Cont act ( f i nal l ong i d, f i nal St r i ng name, f i nal St r i ng phoneNumber ) {
t hi s. i d = i d;
t hi s. name = name;
t hi s. phoneNumber = phoneNumber ;
}

@Over r i de
publ i c St r i ng t oSt r i ng( ) {
r et ur n t hi s. name + " \ n" + t hi s. phoneNumber ;
}
}

pr i vat e cl ass Cont act But t on ext ends But t on {

publ i c Cont act cont act ;

publ i c Cont act But t on( f i nal Cont ext ct x, f i nal Cont act cont act ) {
super ( ct x) ;
t hi s. cont act = cont act ;
}
34


Unidad 7 SQLite


}

@Over r i de
publ i c voi d onCr eat e( f i nal Bundl e i ci cl e) {
super . onCr eat e( i ci cl e) ;
t hi s. set Cont ent Vi ew( R. l ayout . pr ovi der _expl or er ) ;

t hi s. addName = ( Edi t Text ) f i ndVi ewByI d( R. i d. add_name) ;
t hi s. addPhoneNumber = ( Edi t Text ) f i ndVi ewByI d( R. i d. add_phone_number ) ;
t hi s. edi t Name = ( Edi t Text ) f i ndVi ewByI d( R. i d. edi t _name) ;
t hi s. edi t PhoneNumber = ( Edi t Text ) f i ndVi ewByI d( R. i d. edi t _phone_number ) ;
t hi s. addCont act = ( But t on) f i ndVi ewByI d( R. i d. add_cont act _but t on) ;
t hi s. addCont act . set OnCl i ckLi st ener ( new OnCl i ckLi st ener ( ) {

publ i c voi d onCl i ck( f i nal Vi ew v) {
addCont act ( ) ;
}
}) ;
t hi s. edi t Cont act = ( But t on) f i ndVi ewByI d( R. i d. edi t _cont act _but t on) ;
t hi s. edi t Cont act . set OnCl i ckLi st ener ( new OnCl i ckLi st ener ( ) {

publ i c voi d onCl i ck( f i nal Vi ew v) {
edi t Cont act ( ) ;
}
}) ;
}

Para comenzar la actividad ProviderExplorer creamos una sencilla clase interna para representar un registro
Contact (no es una representacin completa pero captura los campos que nos interesan). Tras ello,
incluimos otra clase interna para representar ContactButton, clase que ampla Button e incluye una
referencia a un determinado contacto.


Despus de establecer los botones Add y Edit, creamos implementaciones OnClickListener annimas que
invocan los correspondientes mtodos add y edit al hacer clic en un botn.


Con esto terminan las tareas de configuracin de ProviderExplorer. A continuacin implementaremos el
mtodo onStart, que aade ms botones dinmicamente para completar y eliminar datos.


@Over r i de
publ i c voi d onSt ar t ( ) {

super . onSt ar t ( ) ;
Li st <Cont act > cont act s = get Cont act s( ) ;
Li near Layout . Layout Par ams par ams = new Li near Layout . Layout Par ams( 200,
andr oi d. vi ew. Vi ewGr oup. Layout Par ams. WRAP_CONTENT) ;
i f ( cont act s ! = nul l ) {
Li near Layout edi t Layout = ( Li near Layout )
f i ndVi ewByI d( R. i d. edi t _but t ons_l ayout ) ;
Li near Layout del et eLayout = ( Li near Layout )
f i ndVi ewByI d( R. i d. del et e_but t ons_l ayout ) ;
par ams. set Mar gi ns( 10, 0, 0, 0) ;

f or ( Cont act c : cont act s) {
Cont act But t on cont act Edi t But t on = new Cont act But t on( t hi s, c) ;
cont act Edi t But t on. set Text ( c. t oSt r i ng( ) ) ;
35


Unidad 7 SQLite


edi t Layout . addVi ew( cont act Edi t But t on, par ams) ;
cont act Edi t But t on. set OnCl i ckLi st ener ( new OnCl i ckLi st ener ( ) {

publ i c voi d onCl i ck( f i nal Vi ew v) { Cont act But t on vi ew
= ( Cont act But t on) v;
edi t Name. set Text ( vi ew. cont act . name) ;
edi t PhoneNumber . set Text ( vi ew. cont act . phoneNumber ) ;
cont act I d = vi ew. cont act . i d;
}
}) ;

Cont act But t on cont act Del et eBut t on = new Cont act But t on( t hi s, c) ;
cont act Del et eBut t on. set Text ( " Del et e " + c. name) ;
del et eLayout . addVi ew( cont act Del et eBut t on, par ams) ;
cont act Del et eBut t on. set OnCl i ckLi st ener ( new OnCl i ckLi st ener ( ) {

publ i c voi d onCl i ck( f i nal Vi ew v) {
Cont act But t on vi ew = ( Cont act But t on) v;
cont act I d = vi ew. cont act . i d;
del et eCont act ( ) ;
}
}) ;
}
} el se {
Li near Layout l ayout = ( Li near Layout ) f i ndVi ewByI d( R. i d. edi t _but t ons_l ayout ) ;
Text Vi ew empt y = new Text Vi ew( t hi s) ;
empt y. set Text ( " No cur r ent cont act s" ) ;
l ayout . addVi ew( empt y, par ams) ;
}
}


El mtodo onStart () invoca el mtodo getContacts que (vase el listado 5.14) devuelve una lista de los
objetos Contact actuales de la base de datos de contactos de Android. Una vez obtenidos los contactos,
iteramos por los mismos y creamos dinmicamente un diseo en el cdigo para edit y delete,
respectivamente. Seguidamente, creamos objetos de vista, incluido ContactButton para completar un
formulario de edicin y un botn para eliminar un contacto. Tras ello, cada botn se aade manualmente a
su correspondiente LinearLayout al que hemos hecho referencia a travs de R.java.
Una vez aadido el mtodo onStart, tenemos una vista para mostrar todos los contactos actuales y todos
los botones, estticos y dinmicos, necesarios para aadir, editar y eliminar datos de contactos.
Seguidamente, implementamos los mtodos para realizar estas acciones, para lo que utilizamos
ContentResolver y otras clases relacionadas.
Inicialmente tendremos que completar la pantalla de contactos actuales para lo que necesitamos consultar
(leer) datos.


Consultando datos


La clase Activity dispone de un mtodo managedQuery que se utiliza para invocar clases ContentProvider
registradas. Al crear nuestro propio ContentProvider en un apartado posterior, veremos cmo se registran
proveedores en la plataforma; por el momento, nos centraremos en la invocacin de mtodos existentes.
Cada proveedor debe publicar el CONTENT_URI que admite. Para consultar el proveedor de contactos,
36


Unidad 7 SQLite

(vase el listado que se presenta a continuacin), necesitamos saber este URI y obtener un Cursor
mediante la invocacin de managedQuery.


private List<Contact> getContacts() {
List<Contact> results = null;
long id = 0L;
String name = null;
String phoneNumber = null;
String[] projection = new String[] { BaseColumns._ID, PeopleColumns.NAME,
PhonesColumns.NUMBER };
ContentResolver resolver = getContentResolver();
Cursor cur = resolver.query(Contacts.People.CONTENT_URI, projection, null, null,
Contacts.People.DEFAULT_SORT_ORDER);

while (cur.moveToNext()) {
if (results == null) {
results = new ArrayList<Contact>();
}
id = cur.getLong(cur.getColumnIndex(BaseColumns._ID));
name = cur.getString(cur.getColumnIndex(PeopleColumns.NAME));
phoneNumber = cur.getString(cur.getColumnIndex(PhonesColumns.NUMBER));
results.add(new Contact(id, name, phoneNumber));
}
return results;
}


En realidad, la base de datos de contactos de Android est formada por varios tipos de datos. Un contacto
incluye detalles de una persona (nombre, empresa, fotografa, etc.), uno o varios nmeros de telfono
(cada uno con un nmero, tipo, etiqueta y dems) e informacin adicional. ContentProvider suele
proporcionar todos los detalles del URI y los tipos que admite como constantes en una clase. En el paquete
android. provider se incluye una clase Contacts correspondiente al proveedor de contactos. Esta clase
cuenta con clases internas anidadas que representan People y Phones.


A su vez, stas contienen clases internas con constantes que representan campos o columnas de datos para
cada tipo. Esta estructura de clases internas puede resultar complicada de asumir pero simplemente
recuerde que los datos Contacts acaban en varias tablas y que los datos que debe consultar y manipular
provienen de las clases internas de cada tipo.
Las columnas que utilizaremos para establecer y obtener datos se definen en estas clases. nicamente
trabajaremos con la parte correspondiente a individuos y telfonos. Primero creamos una proyeccin de las
columnas que devolver como matriz String. Tras ello, obtenemos una referencia a ContentResolver, que
nos permite obtener un objeto Cursor. Este objeto representa las filas de los datos devueltos, por los que
iteramos para crear los objetos de los contactos.


El mtodo quer y de la clase ContentResolver tambin le permite pasar argumentos adicionales para limitar
los resultados. En concreto, donde pasamos null, null, podemos pasar un filtro para limitar las filas que
devolver en forma de clusula WHERE y objetos opcionales de sustitucin para dicha clusula (inyectados
en ?). Es un uso convencional de SQL, muy sencillo de utilizar. El inconveniente aparece si no se utiliza una
base de datos para ContentProvider.
37


Unidad 7 SQLite

Aunque sea posible, tendr que procesar instrucciones SQL en la implementacin del proveedor y necesita
que todo el que utilice el proveedor tambin lo haga. Despus de ver cmo consultar datos para devolver
resultados, aprenderemos a aadir nuevos datos: una fila.




Insertando datos


El siguiente fragmento forma parte de la clase ProviderExplorer, haciendo nfasis en el mtodo
addContent; el cual se utiliza para aadir elementos de formulario a la actividad e insertar una nueva fila de
datos en las tablas relacionadas con contactos.


pr i vat e voi d addCont act ( ) {
Cont ent Resol ver r esol ver = get Cont ent Resol ver ( ) ;
Cont ent Val ues val ues = new Cont ent Val ues( ) ;

/ / cr eat e Cont act s. Peopl e r ecor d f i r st , usi ng hel per met hod t o get per son i n " My
Cont act s"
/ / gr oup
val ues. put ( Peopl eCol umns. NAME, t hi s. addName. get Text ( ) . t oSt r i ng( ) ) ;
Ur i per sonUr i = Cont act s. Peopl e. cr eat ePer sonI nMyCont act sGr oup( r esol ver , val ues) ;
Log. v( " Pr ovi der Expl or er " , " ADD per sonUr i - " + per sonUr i . t oSt r i ng( ) ) ;

/ / append ot her cont act dat a, l i ke phone number
val ues. cl ear ( ) ;
Ur i phoneUr i = Ur i . wi t hAppendedPat h( per sonUr i ,
Cont act s. Peopl e. Phones. CONTENT_DI RECTORY) ;
Log. v( " Pr ovi der Expl or er " , " ADD phoneUr i - " + phoneUr i . t oSt r i ng( ) ) ;
val ues. put ( PhonesCol umns. TYPE, PhonesCol umns. TYPE_MOBI LE) ;
val ues. put ( PhonesCol umns. NUMBER, t hi s. addPhoneNumber . get Text ( ) . t oSt r i ng( ) ) ;

/ / i nser t manual l y ( t hi s t i me no hel per met hod)
r esol ver . i nser t ( phoneUr i , val ues) ;

st ar t Act i vi t y( new I nt ent ( t hi s, Pr ovi der Expl or er . cl ass) ) ;
}


Lo primero que vemos en el mtodo addContact es la referencia ContentResolver y el uso de un objeto
ContentValues para asignar nombres de columna a valores. Es un tipo de objeto especfico de Android. Una
vez definidas las variables, utilizamos el mtodo de ayuda especial createPersonlnMyContactsGroup de la
clase Contacta . People para aadir un registro y devolver Uri. Este mtodo utiliza Resolver y, entre
bastidores, realiza la insercin. La estructura de la clase Contacts dispone de diversos mtodos de ayuda
(consulte la documentacin) y que permiten reducir la cantidad de cdigo necesario para realizar
determinadas tareas como aadir un contacto al grupo My Contacts (el predeterminado que muestra el
telfono en la aplicacin de contactos).
Tras crear un nuevo registro People, aadimos datos al Uri existente para crear un registro de telfono
asociado a la misma persona. Es una caracterstica del API. Por lo general puede aadir o ampliar un Uri
existente para acceder a distintos aspectos de la estructura de datos. Una vez obtenido el Uri y despus de
establecer y actualizar el objeto de valores, aadimos directamente un registro de telfono, con el mtodo
ContentResolver insert (no el de ayuda).
Tras aadir los datos, veremos cmo actualizar datos ya existentes.
38


Unidad 7 SQLite



Actualizando datos


Para actualizar una fila de datos primero debe obtener una referencia de fila Cursor y utilizar los mtodos
de actualizacin de Cursor.


pr i vat e voi d edi t Cont act ( ) {
Cont ent Resol ver r esol ver = get Cont ent Resol ver ( ) ;
Cont ent Val ues val ues = new Cont ent Val ues( ) ;

/ / anot her way t o append t o a Ur i , use bui l dUpon
Ur i per sonUr i =
Cont act s. Peopl e. CONTENT_URI . bui l dUpon( ) . appendPat h( Long. t oSt r i ng( t hi s. cont act I d) ) . bui l d( )
;
Log. v( " Pr ovi der Expl or er " , " EDI T per sonUr i - " + per sonUr i . t oSt r i ng( ) ) ;

/ / once we have t he per son Ur i we can edi t per son val ues, l i ke name
val ues. put ( Peopl eCol umns. NAME, t hi s. edi t Name. get Text ( ) . t oSt r i ng( ) ) ;
r esol ver . updat e( per sonUr i , val ues, nul l , nul l ) ;

/ / separ at e st ep t o updat e phone val ues
val ues. cl ear ( ) ;
/ / j ust edi t t he f i r st phone, wi t h i d 1
/ / ( i n r eal l i f e we woul d need t o par se mor e phone dat a and edi t t he cor r ect
phone out of a
/ / possi bl e many)
Ur i phoneUr i = Ur i . wi t hAppendedPat h( per sonUr i ,
Cont act s. Peopl e. Phones. CONTENT_DI RECTORY + " / 1" ) ;
val ues. put ( PhonesCol umns. NUMBER, t hi s. edi t PhoneNumber . get Text ( ) . t oSt r i ng( ) ) ;
r esol ver . updat e( phoneUr i , val ues, nul l , nul l ) ;

st ar t Act i vi t y( new I nt ent ( t hi s, Pr ovi der Expl or er . cl ass) ) ;
}


Al actualizar datos, comenzamos con People. CONTENT_URI y le aadimos una ruta ID concreta por medio
de UriBuilder. Es una clase de ayuda que utiliza el patrn Builder para que pueda construir y acceder a los
componentes de un objeto Uri. Seguidamente, actualizamos los valores e invocamos resolver. update para
realizar la actualizacin. Como puede apreciar, el proceso de actualizacin con ContentResolver es muy
similar al de creacin, con la excepcin de que el mtodo update le permite pasar una clusula WHERE y
objetos de sustitucin (estilo SQL).
En este ejemplo, despus de actualizar el nombre de la persona, necesitamos obtener el Ur i correcto para
actualizar tambin su registro de telfono. Para ello aadimos datos de ruta Uri adicionales a un objeto que
ya tenemos, que adjuntamos al ID especfico deseado. En otras circunstancias, sera necesario determinar
qu registro telefnico del contacto hay que actualizar (en este caso hemos utilizado el ID I para resumir).
Aunque nicamente actualizamos un registro en funcin de un URI concreto, recuerde que puede
actualizar un grupo de registros si utiliza la forma no especfica del URI y la clausula WHERE. Por ltimo,
tendremos que implementar el mtodo delete.


Eliminando datos
39


Unidad 7 SQLite

Para eliminar datos volveremos al objeto ContentResolver utilizado para aadir datos. En esta ocasin
invocaremos el mtodo delete,


pr i vat e voi d del et eCont act ( ) {
Ur i per sonUr i = Cont act s. Peopl e. CONTENT_URI ;
per sonUr i =
per sonUr i . bui l dUpon( ) . appendPat h( Long. t oSt r i ng( t hi s. cont act I d) ) . bui l d( ) ;
Log. v( " Pr ovi der Expl or er " , " DELETE per sonUr i - " + per sonUr i . t oSt r i ng( ) ) ;
get Cont ent Resol ver ( ) . del et e( per sonUr i , nul l , nul l ) ;
st ar t Act i vi t y( new I nt ent ( t hi s, Pr ovi der Expl or er . cl ass) ) ;
}


El concepto de eliminacin es muy similar, una vez comprendido el resto del proceso. Volvemos a utilizar el
enfoque UriBuilder para configurar un Uri para un registro concreto y despus obtenemos una referencia
ContentResolver, en esta ocasin con la invocacin del mtodo delete.


El archivo Manifest y los ContentProviders


Para que la plataforma sepa qu contenido ofrecen los proveedores y qu tipo de datos representan,
deben definirse en un archivo de manifiesto de aplicacin e instalarse en la plataforma. El cdigo muestra
un manifiesto ejemplo haciendo referencia a cierto proveedor.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://sobernas.android.com/apk/res/android"
package="com.msi.manning.chapterS.widget"> Opplication android: icon="@drawable/icon"
android:label="@string/app_short_name"> <activity android:name=".WidgetExplorer" android:
label = "@string/app name"> <intent-filter>
<action android:name="android.intent .action .MAIN" /> Ccategory android: name="android.
intent. category. LAUNCHER" />
</intent-filter> </activity>
<provider android: name="WidgetProvider" android:authorities=
"com.msi.manning.chapterS.Widget" />
</application>
</manifest>


La parte ms importante del manifiesto relacionada con proveedores de contenidos es el elemento
<provider>. Se utiliza para definir la clase que implementa el proveedor y para asociar una determinada
autoridad a dicha clase.
Un proyecto completo capaz de aadir, recuperar, actualizar y eliminar registros nos ha permitido concluir
el anlisis del uso y creacin de clases ContentProvider. Y con ello hemos demostrado muchas de las formas
de almacenar y recuperar datos en la plataforma Android.

Anda mungkin juga menyukai