Demo

Éste es el código completo del ejemplo de manejo de base de datos SQL para esta documentación. Genera una base de datos con una única tabla vacía. El código HTML contiene un botón que añade una nueva fila a la tabla de forma permanente cada vez que se pulsa.

<!DOCTYPE html>
<html lang="es">
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
        <link rel="stylesheet" type="text/css" href="css/index.css" />
        <link rel="stylesheet" type="text/css" href="css/tabla.css" />
        <meta name="msapplication-tap-highlight" content="no" />
        <title>Hello World</title>
        <script type="text/javascript" charset="utf-8" src="js/jquery.min.js"></script>
		   <script type="text/javascript" charset="utf-8">

			// Wait for Cordova to load
			//
			document.addEventListener("deviceready", onDeviceReady, false);
			// Populate the database 
			//
			var n = 0;

			function populateDB(tx) {
				tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)');
			}

			function nuevoDB(tx){
				n++;
				tx.executeSql('INSERT INTO DEMO (id, data) VALUES ('+n+', "New row")');
			}

			// Query the database
			//
			function queryDB(tx) {
				tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
			}

			function queryDB2(tx) {
				tx.executeSql('SELECT * FROM DEMO', [], querySuccess2, errorCB);
			}

			// Query the success callback
			//
			function querySuccess(tx, results) {
				var len = results.rows.length;
				n = len;
					document.getElementById("bd").innerHTML += "<tr><td>ID</td><td>DATA</td></tr>";
					for (var i=0; i<len; i++){
						document.getElementById("bd").innerHTML += "<tr><td>"+results.rows.item(i).id+"</td><td>"+results.rows.item(i).data+"</td></tr>";
					}
			}

			function querySuccess2(tx, results) {
				var len = results.rows.length;
						document.getElementById("bd").innerHTML += "<tr><td>"+results.rows.item(len-1).id+"</td><td>"+results.rows.item(len-1).data+"</td></tr>";
			}

			// Transaction error callback
			//
			function errorCB(err) {
				alert("Error processing SQL: "+err.code);
			}

			// Transaction success callback
			//
			function successCB() {
				var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
				db.transaction(queryDB, errorCB);
			}

			function successCB2() {
				var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
				db.transaction(queryDB2, errorCB);
			}

			// Cordova is ready
			//
			function onDeviceReady() {
				var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
				db.transaction(populateDB, errorCB, successCB);

				$("#nuevo").click(function() {
				  db.transaction(nuevoDB, errorCB, successCB2);
				});
			}

			</script>
    </head>
    <body>
        <div class="app">
            <h1>Apache Cordova</h1>
            <div class="generatecss_dot_com_table">
					<table id="bd"></table>
				</div>
            <br/><button id="nuevo">NUEVA FILA</button><br/>
            <div id="deviceready" class="blink">
                <p class="event listening">Connecting to Device</p>
                <p class="event received">Device is Ready</p>
				<p>EJEMPLO BASE DE DATOS SQL</p>
            </div>
            
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
        <script type="text/javascript">
            app.initialize();
        </script>
    </body>
</html>

La clave está en saber manejar bien las funciones callback. Cada función que trabaja la consulta llama a una o varias funciones de este tipo. Cuando se da un error, siempre se llamará a la función errorCB() que muestra el código de error SQL utilizando el objeto SQLError.

 

function onDeviceReady() {
    var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
    db.transaction(populateDB, errorCB, successCB);
    $("#nuevo").click(function() {
        db.transaction(nuevoDB, errorCB, successCB2);
    });
}

El código contiene dos conjuntos de funciones diferenciados: las funciones relacionadas con la creación de la tabla y las que añaden nuevas filas cuando se pulsa el botón. Sin embargo, se utiliza el mismo objeto Database para todas ellas una vez que la API de Cordova está completamente cargada (evento deviceready).

La función populateDB() se encarga de crear la tabla, donde tx es la referencia la objeto SQLTransaction:

function populateDB(tx) {
     tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)');
}

Por otra parte, nuevoDB() se encarga de agregar una nueva fila en base a una variable global n que se va autoincrementando, ya que el campo ID de la tabla es único:

function nuevoDB(tx){
    n++;
    tx.executeSql('INSERT INTO DEMO (id, data) VALUES ('+n+', "New row")');
}

Las funciones queryDB() y queryDB2() son las que realizan la consulta SQL que devolverá el número de filas afectadas. El código es el mismo en ambas, pero ha sido necesario repetir código en este caso, debido a que las funciones callback son diferentes.

function queryDB(tx) {
    tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
}

Las funciones querySuccess() y querySuccess2() son las que se encargan de volcar los datos de las filas devueltas por la consulta en una tabla HTML, actualizando los datos. En el caso de querySuccess2() solamente se añade la nueva fila creada (cuando se pulsa el botón).

function querySuccess(tx, results) {
    var len = results.rows.length;
    n = len;
    document.getElementById("bd").innerHTML += "<tr><td>ID</td><td>DATA</td></tr>";
    for (var i=0; i<len; i++){
        document.getElementById("bd").innerHTML += "<tr><td>"+results.rows.item(i).id+"</td><td>"+results.rows.item(i).data+"</td></tr>";
    }
}
function querySuccess2(tx, results) {
    var len = results.rows.length;
    document.getElementById("bd").innerHTML += "<tr><td>"+results.rows.item(len-1).id+"</td><td>"+results.rows.item(len-1).data+"</td></tr>";
}

Una vez comprendido el funcionamiento de la aplicación, podemos pasar a ver su funcionamiento real: