Jak korzystać z przygotowanych wyciągów w SQlite w Androidzie?
Jak korzystać z przygotowanych wyciągów w SQlite w Androidzie?
Odpowiedzi:
Cały czas korzystam z przygotowanych wyciągów w Androidzie, to dość proste:
SQLiteDatabase db = dbHelper.getWritableDatabase();
SQLiteStatement stmt = db.compileStatement("INSERT INTO Country (code) VALUES (?)");
stmt.bindString(1, "US");
stmt.executeInsert();
SQLiteStatement.bindXXX()
indeks ma wartość 1, a nie 0, jak większość z nich.
Dla przygotowanych instrukcji SQLite w systemie Android jest SQLiteStatement . Przygotowane instrukcje pomagają przyspieszyć działanie (szczególnie w przypadku instrukcji, które muszą być wykonywane wielokrotnie), a także pomagają uniknąć ataków polegających na iniekcji. Zobacz ten artykuł, aby zapoznać się z ogólną dyskusją na temat przygotowanych wypowiedzi.
SQLiteStatement
jest przeznaczony do użytku z instrukcjami SQL, które nie zwracają wielu wartości. (Oznacza to, że nie użyjesz ich do większości zapytań). Poniżej znajduje się kilka przykładów:
String sql = "CREATE TABLE table_name (column_1 INTEGER PRIMARY KEY, column_2 TEXT)";
SQLiteStatement stmt = db.compileStatement(sql);
stmt.execute();
execute()
Sposób nie zwraca wartość tak, że jest odpowiedni do użycia z tworzenia i usuwania, lecz nie są przeznaczone do stosowania z wybranych przez użytkownika, Wstawianie, usuwanie i UPDATE, ponieważ obie te wartości. (Ale spójrz na to pytanie .)
String sql = "INSERT INTO table_name (column_1, column_2) VALUES (57, 'hello')";
SQLiteStatement statement = db.compileStatement(sql);
long rowId = statement.executeInsert();
Zwróć uwagę, że executeInsert()
metoda jest używana zamiast execute()
. Oczywiście nie chciałbyś zawsze wpisywać te same rzeczy w każdym wierszu. Do tego możesz użyć wiązań .
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();
Zwykle używasz przygotowanych instrukcji, gdy chcesz szybko coś powtórzyć (np. INSERT) wiele razy. Przygotowana instrukcja sprawia, że instrukcja SQL nie musi być za każdym razem analizowana i kompilowana. Możesz jeszcze bardziej przyspieszyć, korzystając z transakcji . Pozwala to na jednoczesne zastosowanie wszystkich zmian. Oto przykład:
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();
}
Sprawdź te linki, aby uzyskać więcej przydatnych informacji na temat transakcji i przyspieszenia wstawiania do bazy danych.
To jest podstawowy przykład. Możesz również zastosować koncepcje z powyższej sekcji.
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();
Ta executeUpdateDelete()
metoda może być również używana do instrukcji DELETE i została wprowadzona w API 11. Zobacz to pytanie i odpowiedź .
Oto przykład.
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();
}
Zwykle po uruchomieniu zapytania chcesz odzyskać kursor z wieloma wierszami. SQLiteStatement
Jednak nie do tego służy. Nie uruchamiasz z nim zapytania, chyba że potrzebujesz tylko prostego wyniku, takiego jak liczba wierszy w bazie danych, którą możesz zrobićsimpleQueryForLong()
String sql = "SELECT COUNT(*) FROM table_name";
SQLiteStatement statement = db.compileStatement(sql);
long result = statement.simpleQueryForLong();
Zwykle query()
w celu uzyskania kursora uruchomisz metodę SQLiteDatabase .
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);
Zobacz tę odpowiedź, aby uzyskać szczegółowe informacje na temat zapytań.
clearBindings()
nie tylko ustawia je na null
(zobacz kod źródłowy ). Patrzę na to jako oczyszczanie stanu, dzięki czemu nic nie wpływa na niego z poprzedniej pętli. Może to jednak nie jest konieczne. Byłbym zadowolony, gdyby ktoś wiedział, że może to skomentować.
Jeśli chcesz mieć kursor po powrocie, możesz rozważyć coś takiego:
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"));
Zobacz ten fragment Genscripts na wypadek, gdybyś chciał mieć pełniejszy. Zauważ, że jest to sparametryzowane zapytanie SQL, więc w zasadzie jest to przygotowana instrukcja.
Przykład jasonhudgins nie zadziała. Nie można wykonać zapytania zi stmt.execute()
odzyskać wartość (lub a Cursor
).
Możesz prekompilować tylko instrukcje, które albo nie zwracają żadnych wierszy (takich jak instrukcja wstawiania lub tworzenia tabeli), albo pojedynczy wiersz i kolumnę (i użyj simpleQueryForLong()
lub simpleQueryForString()
).