如何在Android的SQlite中使用准备好的语句?
如何在Android的SQlite中使用准备好的语句?
Answers:
我一直在Android中使用准备好的语句,这很简单:
SQLiteDatabase db = dbHelper.getWritableDatabase();
SQLiteStatement stmt = db.compileStatement("INSERT INTO Country (code) VALUES (?)");
stmt.bindString(1, "US");
stmt.executeInsert();
SQLiteStatement.bindXXX()
具有从1开始的索引,而不像大多数索引那样从0开始。
对于Android中准备好的SQLite语句,有SQLiteStatement。准备好的语句可以帮助您提高性能(特别是对于需要多次执行的语句),还可以避免注入攻击。有关准备好的语句的一般讨论,请参见本文。
SQLiteStatement
旨在与不返回多个值的SQL语句一起使用。(这意味着您不会在大多数查询中使用它们。)下面是一些示例:
String sql = "CREATE TABLE table_name (column_1 INTEGER PRIMARY KEY, column_2 TEXT)";
SQLiteStatement stmt = db.compileStatement(sql);
stmt.execute();
该execute()
方法不返回值,因此适合与CREATE和DROP一起使用,但不适用于SELECT,INSERT,DELETE和UPDATE,因为这些返回值。(但请参阅此问题。)
String sql = "INSERT INTO table_name (column_1, column_2) VALUES (57, 'hello')";
SQLiteStatement statement = db.compileStatement(sql);
long rowId = statement.executeInsert();
请注意,使用的executeInsert()
是方法而不是execute()
。当然,您不希望总是在每一行中输入相同的内容。为此,您可以使用绑定。
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();
通常,当您想多次快速重复某些内容(例如INSERT)时,可以使用准备好的语句。准备好的语句使得它不必每次都解析和编译SQL语句。您可以通过使用事务来加快处理速度。这允许立即应用所有更改。这是一个例子:
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();
}
请查看这些链接,以获取有关事务和加快数据库插入速度的更多信息。
这是一个基本的例子。您也可以应用以上部分中的概念。
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();
该executeUpdateDelete()
方法也可以用于DELETE语句,并且已在API 11中引入。请参阅此Q&A。
这是一个例子。
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();
}
通常,当您运行查询时,您希望使游标返回很多行。不过,这不是SQLiteStatement
为了什么。除非只需要一个简单的结果(例如数据库中的行数),否则您就不使用它来运行查询simpleQueryForLong()
String sql = "SELECT COUNT(*) FROM table_name";
SQLiteStatement statement = db.compileStatement(sql);
long result = statement.simpleQueryForLong();
通常,您将运行SQLiteDatabase的query()
方法来获取游标。
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);
有关查询的更多详细信息,请参见此答案。
如果您想让游标返回,则可以考虑以下内容:
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"));