SQLITE
SQLITE
INTRODUCCIN
SqLite es un motor de base de datos creado en el ao 2000 por el Dr. Richard Hipp. Actualmente es el motor de bases de datos ms utilizado en el mundo ya que se encuentra presente en dispositivos con distintos sistemas operativos (Android, IOS, Symbiam, etc.) y en Moizilla Firefox, PHP, Skype, Adobe AIR, etc. Internamente, SQLite est construida por una pequea librera multiplataforma desarrollada en C que implementa un sistema gestor de bases de datos. SQLite puede utilizarse para guardar datos que no requieran gran cantidad de informacin como configuraciones, logs, historiales, etc. Actualmente SQLite 3 soporta hasta 2 Terabytes, pero hay que tener en cuenta que SQLite consume al rededor de 256 bytes de memoria por cada 1 MiB de la base de datos. SQLite es, como indican en un artculo de su propia web oficial, una base de datos de cdigo libre con las siguientes caractersticas distintivas: No necesita configuracin, ni tras la instalacin inicial ni para el posterior mantenimiento. No utiliza servidor. Se puede utilizar embebida dentro de otra aplicacin o gestionar los ficheros de datos a travs de una pequea aplicacin de consola descargable desde su web. Utiliza un slo fichero para almacenar los datos. Una base de datos de SQLite se compone de un nico fichero que puede almacenarse en cualquier ruta de la mquina. Los ficheros de datos son multiplataforma. Una base de datos creada en una mquina y sistema operativo concreto puede copiarse y utilizarse bajo cualquier otra plataforma. Es muy compacta. La librera que se integra con otras aplicaciones ocupa unos 200 KBytes. Utiliza tipado dinmico (Manifest Typing). SQLite permite almacenar cualquier valor de cualquier tipo en cualquier registro de una tabla de la base de datos, independientemente del tipo declarado al crear la tabla. Utiliza registros de longitud variable. Cada dato almacenado en la base de datos ocupar su tamao real y no el reservado segn su tipo.
SQLite, utiliza el lenguaje SQL para las consultas (SELECT), manipulacin de datos (INSERT, DELETE, etc.), y de definicin de datos (CREATE TABLE, etc).
SQLite presenta unas pequeas variaciones del estndar SQL-92 que aplica para la mayora de bases de datos SQL, por ello como no permite el uso de FOREIGN KEY, RIGHT OTHER JOIN, FULL OTHER JOIN y algunos usos de ALTER TABLE. Las bases de datos SQLite slo pueden ser accedidas por la aplicacin en la que fueron creadas. En caso de necesitar compartir la base de datos en distintas aplicaciones se deben utilizar Content Providers. Las bases de datos SQLite se almacenan en la carpeta data/data/[nombre paquete]/databases/nombreBaseDatos La carpeta donde est almacenada la base de datos no es accesible por los usuarios convencionales, tan slo puede acceder el usuario root. La ruta de data nos la puede aportar la orden Evironment.getDataDirector() Desde el dispositivo virtual s se puede acceder a la carpeta donde est la base de datos.
RESUMEN SQL
Insercin INSERT INTO "nombre_tabla ("columna1", "columna2", ...) VALUES ("valor1", "valor2", ...) UPDATE "nombre_tabla" SET "columna_1" = [nuevo valor] WHERE {condicin} DELETE FROM "nombre_tabla" WHERE {condicin} SELECT "nombre1_columna", "nombre2_columna" FROM "nombre_tabla" WHERE {condicin} ORDER BY "nombre_columna" [ASC, DESC]
Modificacin
Eliminacin Consulta
CLASE SQLiteOpenHelper
Lo primero que haremos es crear una clase que herede de SQLiteOpenHelper. Esta clase nos permite crear la base de datos y actualizar la estructura de tablas y datos iniciales.
Debemos implementar el constructor y sobrescribir los mtodos onCreate() y onUpgrade(). El mtodo onCreate() es llamado cuando la base de datos se crea por primera vez. Aqu es donde se define la estructura de las tablas y se cargan eventualmente los datos iniciales. Para ejecutar las sentencias SQL se dispone del mtodo exexSQL(orden SQL) de la instancia de SQLiteDatabase que se recibe por parmetro. El mtodo onUpgrade() se ejecuta automticamente cuando se requiera de una actualizacin de la base de datos (agregar/eliminar/modificar tablas o/y campos). En los parmetros del mtodo onUpgrade() se recibe un identificativo de la antigua versin y de la versin nueva. En nuestro ejemplo implementaremos una nueva clase llamada BaseDatos que herede de la clase SQLiteOpenHelper: public class BaseDatosHelper extends SQLiteOpenHelper { public BaseDatosHelper (Context context, String nombre, CursorFactory factory, int version) { super(context, nombre, factory, version); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table usuarios (id int primary key, nombre text, pasword text, email text)"); 3
} @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("drop table if exists usuarios"); db.execSQL("create table usuarios (id int primary key, nombre text, pasword text, email text)"); } }
Para acceder a la base de datos debemos seguir los siguientes pasos 1. Crear un objeto de la clase BaseDatosHelper y establecer la conexin 2. Abrir la base de datos para lectura o/y escritura. 3. Leer o/y escribir datos en la base de datos. Crear un objeto de la clase BaseDatosHelper y establecer la conexin BaseDatosHelper bdHelper = new BaseDatosHelper (this, nombre, null, version) Donde: this: contexto de la actividad actual nombre: cadena que representa el nombre con el que identificar a la base de datos null: objeto CursorFactory que normalmente no es necesario, nosotros utilizaremos null. 4
versin: nmero entero que identifica la versin actual con la que queremos trabajar, si la versin fuese superior a la ya existente se ejecutara el mtodo onUpgrade() de la clase BaseDatosHelper.
Al crear un objeto de la clase BaseDatosHelper se producen de forma automtica las siguientes operaciones: a) Si la base de datos no est creada, se procede a la ejecucin del mtodo onCreate() de la clase BaseDatosHelper. b) Si el nmero de versin es superior al de la base de datos existente, se ejecuta el mtodo onUpgrade() de la clase BaseDatosHelper c) Si la base de datos ya existe y la versin que se demanda es la misma que la ya existente, simplemente se abre la conexin con la base de datos. Abrir la base de datos para lectura o escritura. Cuando la conexin con la base de datos ya est establecida, se proceder a la apertura de la base de datos. A la hora de abrir la base de datos debemos indicar si las operaciones que vamos a realizar son slo de lectura o tambin lo son de escritura. Para abrir la base de datos en forma de solo lectura se debe ejecutar el mtodo getReadableDatabase() sobre la instancia de BaseDatosHelper. SQLiteDatabase bd= bdHelper.getReadableDatabase(); Para abrir la base de datos en forma de lectura/escritura se debe ejecutar el mtodo getWritableDatabase() sobre la instancia de la base de datos SQLiteDatabase bd = bdHelper.getWritableDatabase(); Estos mtodos devuelven una instancia de SQLiteDatabase que permite utilizar el mtodo execSQL() para ejecutar cualquier instruccin SQL de manipulacin de datos. Leer o/y escribir datos en la base de datos Una vez abierta la base de datos, podemos acceder a la informacin que contiene para leer o/y escribir datos a partir de la referencia de SQLiteDatabase creada (db) Por ejemplo, el siguiente cdigo abre la base de datos para escritura y le incorpora 3 registros. public class MiBaseDatos extends Activity{ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //Abrir la conexin con la base de datos 5
BaseDatosHelper dbHelper= new BaseDatosHelper (this, "UsuariosBD", null, 1); //Abrir la base de datos 'UsuariosBD' en modo escritura SQLiteDatabase db = dbHelper.getWritableDatabase(); //Si hemos abierto correctamente la base de datos if(db != null){ //Insertar 4 usuarios for(int i=1; i<=3; i++){ //Generar los datos int codigo = i; String nombre = "Usuario" + i; //Insertar los datos en la tabla Usuarios db.execSQL("INSERT INTO Usuarios (codigo, nombre) VALUES ?, ?", new String[]{String.ValueOf(cdigo),nombre}); } //Cerrar la base de datos db.close(); } } } rawQuery y execSQL Cursor rawQuery (String sql, String[] selecArgs ) sql: consulta SQL a ejecutar selecArgs: array de argumentos a sustituir por las ? que existan en la consulta sql retorno: cursor posicionado en la primera entrada. sql: consulta SQL a ejecutar
No devuelve resultados
PATRN DE CAPAS
El patrn arquitectnico llamado patrn de capas se utiliza para plantear muchas soluciones a problemas ms o menos complejos. Este patrn nos ayuda a separar las distintas responsabilidades de la aplicacin en lo que se denomina capas. De esta forma habr una capa encargada de tratar con el origen de datos (bases de datos, ficheros XML. etc), otra capa destinada a la lgica de negocio de la aplicacin (utilizar esos datos obtenidos para realizar distintas operaciones) y otra capa destinada a presentar las vistas (la parte de la interfaz de usuario). 6
La estructura de capas favorecer el mantenimiento de la aplicacin, la reutilizacin del cdigo y su escalabilidad. Para conocer este patrn analizaremos un ejemplo en el que se desea desarrollar un sistema empresarial, donde se pretende manejar la informacin de presupuestos para los clientes de la empresa. Es necesario conocer los precios internos, elaborar el presupuesto, acceder al inventario de los productos, y contemplar los datos e historia del cliente que pide el presupuesto. La informacin debe estar disponible para ser consultada por la Web, y provenir de distintas fuentes de datos. Se pretende organizar la arquitectura del sistema para que sea flexible, por ejemplo, que contemple las distintas formas de acceder a los datos, y las formas de procesarlos, y por ltimo, los distintos modos de visualizar el resultado. Podemos tomar la decisin de separar la aplicacin segn este esquema:
Este patrn debe evitar que el cambio en una capa altere mnimamente las otras capas. La prueba ms difcil, en nuestro ejemplo, podra ser: al cambiar las fuentes de datos (las bases de datos usadas), poco debera afectar a la capa de presentacin. Y si el da de maana queremos incorporar una capa de presentacin distinta (como un sistema de atencin automtica por telfono), no debera alterar a las otras capas ya desarrolladas. Si bien en este ejemplo, las capas que elegimos construir son las de presentacin, negocio y datos, el patrn es lo suficientemente general para aplicarse en otras situaciones.
ContentValues
Para el manejo de los datos directamente sobre la base de datos utilizaremos la clase ContentValues que permite crear y actualizar valores. A travs de la clase ContentValues se manipulan datos organizados en pares identificador/valor, donde identificador es el nombre el campo y el valor su contenido. 8
A la clase CapaAccesoDatos debemos agregar los mtodos que se prevean necesario para el trabajo con la base de datos. Insertar un registro long insert (String table, String nullColumnaHack, ContentValues values) table: nombre de la table nullColumnHack: null o nombre de una columna si values no contiene ningn par columna-valor. values: conjunto de pares columna/valor que se quiere insertar devuelve el id de la fila o -1 si hubo algn error public long insertarUser (String nombre, String pasword, String email) { long numReg; database = dbHelper.getWritableDatabase(); ContentValues initialValues = createContentValues(nombre, pasword, email); numReg=database.insert(DATABASE_TABLE, null, initialValues); dbHelper.close(); return numReg; } private ContentValues createContentValues(String nombre, String pasword, String email) { ContentValues values = new ContentValues(); values.put(NOMBRE, nombre); values.put(PASWORD, pasword); values.put(EMAIL, email); return values ;
}
Este mtodo devuelve -1 si no se ha podido realizar la tarea y el nmero de fila del registro agregado en caso contrario.
Cursor
Una consulta devuelve un objeto de tipo Cursor. Un cursor es un puntero hacia al primer elemento de la lista resultado de una consulta. De esa forma, Android, no tiene que tener en memoria toda la tabla, sino tan slo el resultado de la consulta. Para moverse entre los distintos elementos de un objeto Cursor se pueden utilizar los mtodos: moveToFirs() y moveToNext(). El mtodo isAfterLast() permite comprobar si se ha alcanzado el final de la lista. El nmero de elementos de un cursor se obtiene con el mtodo getCount().
Para acceder a los datos individuales de un elemento de un objeto cursor se pueden utilizar los mtodos: getLong(columnIndex) -> devuelve el dato de la columna cuyo orden de secuencia es columnIndex y cuyo tipo de Long. getString(columnIndex) -> devuelve el dato de la columna cuyo orden de secuencia es columnIndex y cuyo tipo de String.
El mtodo getColumnIndexOrThrow(String) devuelve el nmero de secuencia de la columna cuyo nombre se pasa por parmetro. Despus de usar un cursor se debe cerrar con el mtodo close(). Acceso a todos los elementos de una tabla En la clase CapaAccesoDatos se debe incluir un mtodo que seleccione todos los registros de una tabla. Cursor query (String tabla, String[] columns, String whereClause, String[] whereArgs, String groupBy, String having, String orderBy) tabla: Nombre de la tabla columns: columnas a devolver, si se pasa null se devuelven todas las columnas whereClause: condicin WHERE o null para acceder a todas las filas (ID=?) whereArgs: lista de Strings que sustituyen a , o null (new String[]{1,3,5) groupBy: Argumentos de GROUP BY, o null si no se aplica. having: Argumentos de HAVING, o null si no se aplica. orderBy: Argumentos de ORDER BY, o null si no se aplica. retorno: Un cursor posicionado en la primera entrada //Devuelve el Cursor que contiene todos los tems public Cursor todosUser(){ database = dbHelper.getReadableDatabase(); Cursor elCursor = database.query(DATABASE_TABLE, new String[] { ID, NOMBRE, PASWORD, EMAIL },null, null, null, null, null); return elCursor; } Para acceder a todos los elementos de la tabla desde una actividad cualquiera: try{ //Crear una instancia de la capa de acceso a datos miBaseDatos=new CapaAccesoDatos(this); //Cargar toda la base de datos miBaseDatos.CargarBaseDatos(); }catch (Exception e){ 10
Log.e("MIO",e.toString());} Cursor cursor= miBaseDatos.todosUser();//Crear un cursor para acceder a los datos. if (cursor.moveToFirst()) { //Recorremos el cursor hasta que no haya ms registros do { String usuario = cursor.getString(1); String pasword = cursor.getString(2); String email = cursor.getString(3); info.setText(info.getText()+"\n user: "+usuario+" pasword: "+pasword+" email:"+email); } while(cursor.moveToNext()); } Devuelve un cursor con el registro que tiene un id public Cursor unUser(long id){ Cursor elCursor = database.query(DATABASE_TABLE, new String[] {ID, NOMBRE, PASWORD, EMAIL }, ID + "=?", new String[]{String.ValueOf(cdigo)}, null, null, null); if (elCursor != null) { elCursor.moveToFirst(); } return elCursor; } Devuelve un cursor con el registro con el nombre de usuario indicado public Cursor verPasword(String nombre){ Cursor elCursor = database.query(DATABASE_TABLE, new String[] { ID, NOMBRE, PASWORD, EMAIL }, NOMBRE + "=?", new String[]{nombre}, null, null, null); if (elCursor != null) { elCursor.moveToFirst();} return elCursor; } Actualizar un registro int update (String table, ContentValues, values, String whereClause, String[] whereArgs) table: Nombre de la tabla values: pares columna/valor whereClause: condicin de WHERE (_id=?) whereArgs: lista de Strings que sustituyen a , o null (new String[]{1,3,5) 11
public long updateUser(long id, String nombre, String pasword, String email) { ContentValues updateValues = createContentValues(nombre, pasword, email); return database.update(DATABASE_TABLE, updateValues, ID + "=?",new String[]{String.valueOf(id)}); } Eliminar un registro int delete (String Table, String whereClause, String[] whereArgs table: Nombre de la tabla whereClause: condicin de WHERE (_id=?) whereArgs: lista de Strings que sustituyen a , o null (new String[]{1,3,5) retorno: nmero de filas afectadas si la clausula Where no es null, 0 si lo es.
DAOSDFSDFS
DAL
Activity
Nota: Una buena prctica es crear una clase por tabla y almacenar los datos obtenidos por el cursor en un array de la clase de objeto correspondiente.
12
ENLACES SQLite
http://sqlite-latino.blogspot.com.es/ http://www.vogella.de/articles/AndroidSQLite/article.html http://www.higherpass.com/Android/Tutorials/Accessing-Data-With-Android-Cursors/ http://www.slideshare.net/paalvarador/sqlite-en-android http://www.slideshare.net/CarlosIglesias3/tema-4-51accesodatos
13