¿Cómo uso las declaraciones preparadas en SQlite en Android?

¿Cómo uso las declaraciones preparadas en SQlite en Android?

Utilizo declaraciones preparadas en Android todo el tiempo, es bastante simple:

SQLiteDatabase db = dbHelper.getWritableDatabase(); SQLiteStatement stmt = db.compileStatement("SELECT * FROM Country WHERE code = ?"); stmt.bindString(1, "US"); stmt.execute(); 

Para las declaraciones preparadas de SQLite en Android hay SQLiteStatement . Las declaraciones preparadas lo ayudan a acelerar el rendimiento (especialmente para las declaraciones que deben ejecutarse varias veces) y también ayudan a evitar los ataques de inyección. Vea este artículo para una discusión general sobre declaraciones preparadas.

SQLiteStatement está destinado a ser utilizado con sentencias SQL que no devuelven valores múltiples. (Eso significa que no los usaría para la mayoría de las consultas.) A continuación se muestran algunos ejemplos:

Crea una mesa

 String sql = "CREATE TABLE table_name (column_1 INTEGER PRIMARY KEY, column_2 TEXT)"; SQLiteStatement stmt = db.compileStatement(sql); stmt.execute(); 

El método execute() no devuelve un valor, por lo que es apropiado usarlo con CREATE y DROP, pero no se debe usar con SELECT, INSERT, DELETE y UPDATE porque estos devuelven valores. (Pero vea esta pregunta )

Insertar valores

 String sql = "INSERT INTO table_name (column_1, column_2) VALUES (57, 'hello')"; SQLiteStatement statement = db.compileStatement(sql); long rowId = statement.executeInsert(); 

Tenga en cuenta que se utiliza el método executeInsert() lugar de execute() . Por supuesto, no querrá siempre ingresar las mismas cosas en cada fila. Para eso puedes usar enlaces .

 String sql = "INSERT INTO table_name (column_1, column_2) VALUES (?, ?)"; SQLiteStatement statement = db.compileStatement(sql); int intValue = 57; String stringValue = "hello"; statement.bindLong(1, intValue); // 1-based: matches first '?' in sql string statement.bindString(2, stringValue); // matches second '?' in sql string long rowId = statement.executeInsert(); 

Usualmente usa declaraciones preparadas cuando quiere repetir algo rápidamente (como un INSERT) muchas veces. La sentencia preparada hace que la sentencia SQL no tenga que ser analizada y comstackda cada vez. Puede acelerar aún más las cosas mediante el uso de transacciones . Esto permite que todos los cambios se apliquen a la vez. Aquí hay un ejemplo:

 String stringValue = "hello"; try { db.beginTransaction(); String sql = "INSERT INTO table_name (column_1, column_2) VALUES (?, ?)"; SQLiteStatement statement = db.compileStatement(sql); for (int i = 0; i < 1000; i++) { statement.clearBindings(); statement.bindLong(1, i); statement.bindString(2, stringValue + i); statement.executeInsert(); } db.setTransactionSuccessful(); // This commits the transaction if there were no exceptions } catch (Exception e) { Log.w("Exception:", e); } finally { db.endTransaction(); } 

Consulte estos enlaces para obtener más información sobre las transacciones y acelerar las inserciones de la base de datos.

  • Compromiso atómico en SQLite (Explicación detallada, vaya a la Parte 3)
  • Transacciones de base
  • Ejemplo de actualización y inserción masiva de Android SQLite
  • Ejemplo de transacción Android SQLite con instrucción preparativa INSERT
  • Acelera tus inserciones de SQLite en Android
  • https://stackoverflow.com/a/8163179/3681880

Actualizar filas

Este es un ejemplo básico. También puede aplicar los conceptos de la sección anterior.

 String sql = "UPDATE table_name SET column_2=? WHERE column_1=?"; SQLiteStatement statement = db.compileStatement(sql); int id = 7; String stringValue = "hi there"; statement.bindString(1, stringValue); statement.bindLong(2, id); int numberOfRowsAffected = statement.executeUpdateDelete(); 

Eliminar filas

El método executeUpdateDelete() también se puede usar para las instrucciones DELETE y se introdujo en la API 11. Consulte esta executeUpdateDelete() Preguntas y respuestas .

Aquí hay un ejemplo.

 try { db.beginTransaction(); String sql = "DELETE FROM " + table_name + " WHERE " + column_1 + " = ?"; SQLiteStatement statement = db.compileStatement(sql); for (Long id : words) { statement.clearBindings(); statement.bindLong(1, id); statement.executeUpdateDelete(); } db.setTransactionSuccessful(); } catch (SQLException e) { Log.w("Exception:", e); } finally { db.endTransaction(); } 

Consulta

Normalmente cuando ejecuta una consulta, quiere recuperar un cursor con muchas filas. Sin embargo, eso no es para lo que SQLiteStatement es. No ejecuta una consulta con él a menos que solo necesite un resultado simple, como el número de filas en la base de datos, que puede hacer con simpleQueryForLong()

 String sql = "SELECT COUNT(*) FROM table_name"; SQLiteStatement statement = db.compileStatement(sql); long result = statement.simpleQueryForLong(); 

Por lo general, ejecutará el método query() de SQLiteDatabase para obtener un cursor.

 SQLiteDatabase db = dbHelper.getReadableDatabase(); String table = "table_name"; String[] columnsToReturn = { "column_1", "column_2" }; String selection = "column_1 =?"; String[] selectionArgs = { someValue }; // matched to "?" in selection Cursor dbCursor = db.query(table, columnsToReturn, selection, selectionArgs, null, null, null); 

Vea esta respuesta para obtener más detalles sobre las consultas.

Si quieres un cursor al regresar, entonces podrías considerar algo como esto:

 SQLiteDatabase db = dbHelper.getWritableDatabase(); public Cursor fetchByCountryCode(String strCountryCode) { /** * SELECT * FROM Country * WHERE code = US */ return cursor = db.query(true, "Country", /**< Table name. */ null, /**< All the fields that you want the cursor to contain; null means all.*/ "code=?", /**< WHERE statement without the WHERE clause. */ new String[] { strCountryCode }, /**< Selection arguments. */ null, null, null, null); } /** Fill a cursor with the results. */ Cursor c = fetchByCountryCode("US"); /** Retrieve data from the fields. */ String strCountryCode = c.getString(cursor.getColumnIndex("code")); /** Assuming that you have a field/column with the name "country_name" */ String strCountryName = c.getString(cursor.getColumnIndex("country_name")); 

Vea este fragmento de Genscripts en caso de que quiera uno más completo. Tenga en cuenta que esta es una consulta SQL parametrizada, por lo que, en esencia, es una statement preparada.

El ejemplo de jasonhudgins no funcionará. No puede ejecutar una consulta con stmt.execute() y obtener un valor (o un Cursor ) de nuevo.

Solo puede precomstackr sentencias que no devuelven ninguna fila (como una inserción o una statement de tabla) o una única fila y columna (y use simpleQueryForLong() o simpleQueryForString() ).

Para obtener un cursor, no puede usar un compiledStatement. Sin embargo, si desea utilizar una statement SQL totalmente preparada, recomiendo una adaptación del método de jbaez … Usando db.rawQuery() lugar de db.query() .