Está en la página 1de 9

Introduccin

El gestor de bases de datos por defecto de Android es Lite. SQLite es una base de datos transaccional ligera que ocupa una cantidad muy pequea de espacio en disco y memoria, de manera que es la eleccin perfecta para crear bases de datos en sistemas operativos para mviles como Android o iOS. Aspectos a tener en cuenta cuando se maneja SQLite: 1. SQLite no dispone de control de integridad, por lo que puedes almacenar un valor de un cierto tipo en un campo de otro tipo distinto (por ejemplo poner un string e un integer o viceversa) 2. SQLite no gestiona directamente la integridad referencial, no soporta restricciones FOREIGN KEY (clave externa) ni sentencias JOIN. No obstante, se puede controlar mediante triggers. 3. El soporte completo de Unicode es opcional y no est instalado por defecto. En este tutorial crearemos una base de datos simple para almacenar la informacin bsica de una serie de empleados. La base de datos dispone de: Tablas 1. TEmpleados 2. TDepartamentos Vistas 1. vistaEmpleados: para visualizar los empleados y los departamentos de la empresa relacionados a los que pertenecen.

Creacin de la base de datos SQL


Por defecto, SQLite no dispone de una interfaz grfica que lo maneje o una aplicacin para gestionar los formularios de la base de datos, por lo que debemos crear nosotros mismos las bases de datos mediante cdigo. Primeramente, crearemos una clase que lleve a cabo todas las operaciones necesarias para tratar la base de datos, tales como crear tablas o insertar y borrar registros. Esa clase ser una clase derivada de SQLiteOpenHelper. Tendremos que sobrecargar los mtodos apropiados, en cada caso, para llevar a cabo la operacin deseada. Slo dispone de dos: 1. onCreate(SQLiteDatabase db): es invocado cuando se crea la base de datos, esto es, cuando creas tablas, campos, vistas o triggers. 2. onUpgrade(SQLiteDatabse db, int oldVersion, int newVersion): es invocado cuando se lleva a cabo una modificacin de la base de datos, como alterar, borrar o crear nuevas tablas. Nuestra clase tendr los siguientes campos:
public class BaseDeDatos extends SQLiteOpenHelper { static final String nombreBD="BDtrabajadores"; static static static static static static static static static final final final final final final final final final String String String String String String String String String tablaEmpleados="TEmpleados"; colID="idEmpleado"; colNombre="nombreEmpleado"; colEdad="edad"; colDept="departamento"; tablaDepartamentos="TDepartamentos"; colDeptID="idDept"; colDeptNombre="nombreDept"; vistaEmps="vistaEmpleados";

El constructor
public BaseDeDatos(Context context) { super(context, nombreBD, null,33); }

El contructor de la superclase tiene los siguientes parmetros:


Context con: el contexto asociado a la base de datos nombreBD: el nombre de la base de datos CursorFactory: a veces, podemos usar una clase que

extiende la clase Cursor para implementar algunas validaciones extra u operaciones sobre las consultas a la base de datos. Si as fuera, pasaramos una instancia de la clase CursorFactory para devolver una referencia a nuestra clase derivada para ser utilizada en lugar del cursor por defecto. En este ejemplo, usaremos la interface

Cursor por defecto para recoger los resultados de las consultas, por lo que el parmetro es null. Version: la versin del esquema de la base de datos. El constructor crea una base de datos en blanco con el nombre y el nmero de versin especificados.

Creando la base de datos


El primer mtodo de la superclase que debemos sobrecargar es onCreate(SQLiteDatabase db):
@Override public void onCreate(SQLiteDatabase bd) { bd.execSQL("CREATE TABLE "+tablaDepartamentos+" ("+colDeptID+ " INTEGER PRIMARY KEY , "+ colDeptNombre+ " TEXT)"); bd.execSQL("CREATE TABLE "+tablaEmpleados+" ("+colID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+ colNombre+" TEXT, "+colEdad+" Integer, "+colDept+" INTEGER NOT NULL ,FOREIGN KEY ("+colDept+") REFERENCES "+tablaDepartamentos+" ("+colDeptID+"));"); bd.execSQL("CREATE TRIGGER fk_empdept_deptid " + " BEFORE INSERT "+" ON "+tablaEmpleados+ " FOR EACH ROW BEGIN"+ " SELECT CASE WHEN ((SELECT "+colDeptID+" FROM "+tablaDepartamentos+" WHERE "+colDeptID+"=new."+colDept+" ) IS NULL)"+ " THEN RAISE (ABORT,'Foreign Key Violation') END;"+ " END;"); bd.execSQL("CREATE VIEW "+vistaEmps+ " AS SELECT "+tablaEmpleados+"."+colID+" AS _id,"+ " "+tablaEmpleados+"."+colNombre+","+ " "+tablaEmpleados+"."+colEdad+","+ " "+tablaDepartamentos+"."+colDeptNombre+""+ " FROM "+tablaEmpleados+" JOIN "+tablaDepartamentos+ " ON "+tablaEmpleados+"."+colDept+" ="+tablaDepartamentos+"."+colDeptID); insertarDepartamentos(bd); }

El mtodo crea las tablas con sus correspondientes campos, una vista y un trigger. El mtodo es invocado cuando se crea la base de datos, es decir, cuando la base de datos no existe en el disco y se ejecuta slo una vez en el mismo dispositivo: la primera vez que la aplicacin corre en dicho dispositivo.

Modificando el esquema de la base de datos.


A veces, necesitamos alterar el esquema de la base de datos, por ejemplo, aadiendo nuevas tablas o cambiando los tipos de los campos. Esto se consigue sobrecargando el mtodo onUpdate(SQLiteDatabase db,int old Version,int newVerison:
@Override public void onUpgrade(SQLiteDatabase bd, int viejaVersion, int nuevaVersion) { bd.execSQL("DROP TABLE IF EXISTS "+tablaEmpleados); bd.execSQL("DROP TABLE IF EXISTS "+tablaDepartamentos); bd.execSQL("DROP bd.execSQL("DROP bd.execSQL("DROP bd.execSQL("DROP onCreate(bd); } TRIGGER TRIGGER TRIGGER VIEW IF IF EXISTS dept_id_trigger"); IF EXISTS dept_id_trigger22"); IF EXISTS fk_empdept_deptid"); EXISTS "+vistaEmps);

Este mtodo es invocado cuando cambia el nmero de versin especificado en el constructor de la clase. Cuando desees incorporar un cambio en el esquema de la base de datos, tendrs que cambiar el nmero de versin en el constructor de la clase. La implementacin ms habitual, como en este caso, consiste en borrar (DROP) las tablas, vistas y triggers creados con anterioridad para crearlos de nuevo.

Manejando claves externas (Foreign-Key)


Hemos mencionado anteriormente que SQLite 3, por defecto, no soporta restricciones de clave externa. Sin embargo, podemos simular dichas restricciones mediante triggers (un trigger -o disparador- es un procedimiento que se ejecuta cuando se cumple una condicin establecida al realizar una operacin de insercin, actualizacin o borrado sobre una base de datos). Crearemos un trigger que garantice que cuando se inserta un nuevo empleado, el valor de departamento est presente en la tabla TDepartamentos. La instruccin SQL para crear un trigger de este tipo tiene el siguiente aspecto:
CREATE TRIGGER fk_empdept_deptid Before INSERT ON TEmpleados FOR EACH ROW BEGIN SELECT CASE WHEN ((SELECT idDept FROM TDepartamentos WHERE idDept = new.departamento ) IS NULL) THEN RAISE (ABORT,'Foreign Key Violation') END; END

Creamos este trigger en el mtodo onCreate tal como sigue:


bd.execSQL("CREATE TRIGGER fk_empdept_deptid " + " BEFORE INSERT "+" ON "+tablaEmpleados+ " FOR EACH ROW BEGIN"+ " SELECT CASE WHEN ((SELECT "+colDeptID+" FROM "+tablaDepartamentos+" WHERE "+colDeptID+"=new."+colDept+") IS NULL)"+ " THEN RAISE (ABORT,'Foreign Key Violation') END;"+ " END;");

Ejecutando sentencias SQL


Empecemos a ejecutar sentencias SQL bsicas. Puedes ejecutar cualquier sentencia SQL de manipulacin de datos que no sea una consulta select, esto es, una operacin insert, delete, o update mediante una llamada a bd.execSQL(String sentenciaSQL):
bd.execSQL("CREATE TABLE "+tablaDepartamentos+" ("+colDeptID+ " INTEGER PRIMARY KEY , "+ colDeptNombre+ " TEXT)");

Insertando nuevos registros


Para insertar nuevas filas en la tabla TDepartamentos usamos el siguiente cdigo:
void insertarDepartamentos(SQLiteDatabase bd) { ContentValues cv=new ContentValues(); cv.put(colDeptID, 1); cv.put(colDeptNombre, "Ventas"); bd.insert(tablaDepartamentos, colDeptID, cv.put(colDeptID, 2); cv.put(colDeptNombre, "Contabilidad"); bd.insert(tablaDepartamentos, colDeptID, cv.put(colDeptID, 3); cv.put(colDeptNombre, "Informtica"); bd.insert(tablaDepartamentos, colDeptID, bd.insert(tablaDepartamentos, colDeptID, }

cv); cv); cv); cv);

Observa que necesitamos invocar al mtodo this.getWritableDatabase() para abrir una conexin de lectura/escritura con la base de datos. La funcin ContentValues.put() tiene dos parmetros: el nombre de la columna y el valor que se le pasa.

Cambiando valores
Para ejecutar una sentencia update disponemos de dos mtodos diferentes: 1. ejecutar bd.execSQL() 2. o invocar el mtodo bd.update():
public int actualizarDatosEmpleado(Empleado emp) { SQLiteDatabase bd=this.getWritableDatabase(); ContentValues cv=new ContentValues(); cv.put(colNombre, emp.getNombre()); cv.put(colEdad, emp.getEdad()); cv.put(colDept, emp.getDept()); return bd.update(tablaEmpleados, cv, colID+"=?", new String []{String.valueOf(emp.getID())}); }

El mtodo update tiene los siguientes parmetros: 1. String Table: la tabla que contien el registro que queremos modificar 2. ContentValues cv: el objeto de contenido que tiene los nuevos valores 3. String where clause: la clusula WHERE para especificar qu registro modificar. 4. String[] args: los argumetnos de la clsular WHERE

Eliminando registros
Como con update, para ejecutar una sentencia delete disponemos de dos mtodos: 1. ejecutar bd.execSQL() 2. o invocar el mtodo bd.delete():
public void eliminarEmpleado(Empleado emp) { SQLiteDatabase bd=this.getWritableDatabase(); bd.delete(tablaEmpleados,colID+"=?", new String [] {String.valueOf(emp.getID())}); bd.close(); }

El mtodo delete tiene los mismo parmetros que el mtodo update.

Ejecutando consultas de seleccin


Para ejecutar consultas de seleccin podemos utilizar dos mtodos: 1. ejecutar bd.rawQuery() 2. o invocar el mtodo db.query() Para ejecutar una consulta tipo raw para recoger todos los departamentos:
Cursor getTodosLosDepartamentos() { SQLiteDatabase bd=this.getReadableDatabase(); Cursor cur=bd.rawQuery("SELECT "+colDeptID+" as _id, "+colDeptNombre+" from "+tablaDepartamentos,new String [] {}); return cur; }

El mtodo rawQuery tiene dos parmetros: 1. String query: la sentencia select 2. String[] selection args: los argumentos si el select incluye una clusula
WHERE

Notas 1. El resultado de una consulta se devuelve en un objeto de la clase Cursor. 2. En una sentencia select si la columna de la clave primaria (el campo id) tiene un nombre distino a _id, entonces tienes que emplear un alias de la forma SELECT [nombre campo] as _id. En otras palabras, el objeto Cursor espera siempre que el campo de la clave primaria tenga como nombre _id, de lo contrario, lanzar una excepcin. Otra forma de llevar a cabo una consulta de seleccin es usando el mtodo bd.query(). Una consulta para listar los empleados de un determinado departamento a partir de una vista tendra el siguiente aspecto:
public Cursor getEmpleadoPorDept(String Dept) { SQLiteDatabase bd=this.getReadableDatabase(); String [] columns=new String[]{"_id",colNombre,colEdad,colDeptNombre}; Cursor c = bd.query(vistaEmps, columns, colDeptNombre+"=?", new String[]{Dept}, null, null, null); return c; }

El mtodo bd.query() tiene los siguientes parmetros: 1. String Table Name: el nombre de la tabla sobre la que se ejecuta la consulta.

2. String [ ] columns: la proyeccin de la consulta, es decir, los campos que se quieren consultar. 3. String WHERE clause: la clusula where; si no hay, pasa el valor null 4. String [ ] selection args: los parmetros de la clusula WHERE 5. String Group by: un string especificando la clusula group by 6. String Having: un string especificando una clusula HAVING 7. String Order By: un string especificando una clusula Order By

Manejando cursores
Los resultados de las consultas se recogen en objetos de tipo Cursor. Existen algunos mtodos comunes que podrs utilizar con los cursores: 1. boolean moveToNext(): avanza el cursor una posicin (siguiente registro) en la tabla de resultados. Devuelve false si el movimiento supone ir ms all del ultimo registro. 2. boolean moveToFirst(): retrocede el cursor hasta el primer registro del conjunto de resultados. Devuelve false si el conjunto de resultados est vaco. 3. boolean moveToPosition(int position): desplaza el cursor a la posicin de un determinado registro. Devuelve false si la posicin no es alcanzable. 4. boolean moveToPrevious(): mueve el cursor al registro anterior al actual en el conjunto de resultados. Devuelve false si la posicin va ms all de la pimera fila. 5. boolean moveToLast(): mueve el cursor al ultimo registro del conjunto de resultados. Devuelve false si el conjunto de resultados est vaco. Tambin existen mtodos muy tiles para comprobar la posicin actual de un cursor: boolean isAfterLast(), isBeforeFirst, isFirst, isLast y isNull(columnIndex). Por otra parte, si tienes un conjunto de resultados con un nico registro y necesitas acceder el valor de un determinado campo del mismo se puede proceder de la siguiente manera:
public int getIDdepartamento(String Dept) { SQLiteDatabase bd=this.getReadableDatabase(); Cursor c=bd.query(tablaDepartamentos, new String[]{colDeptID+ " as _id",colDeptNombre},colDeptNombre+"=?", new String[]{Dept}, null, null, null); c.moveToFirst(); return c.getInt(c.getColumnIndex("_id")); }

Tenemos Cursor.getColumnIndex(String ColumnName) para recuperar el ndice de un campo a partir de su nombre. Despus, para obtener el valor de una determinada columna, tenemos el mtodo Cursor.getInt(int ColumnIndex).

Asimismo estn los mtodos getShort, getString, getDouble, y getBlob para devolver los valores como un array de bytes. Es una buena prctica cerrar un cursor despus de haberlo usado mediante close().

También podría gustarte