如何在Android中的SQlite中使用准备好的语句?
如何在Android中的SQlite中使用准备好的语句?
我始终在Android中使用准备好的语句,这很简单:
SQLiteDatabase db = dbHelper.getWritableDatabase(); SQLiteStatement stmt = db.compileStatement("SELECT * FROM Country WHERE code = ?"); stmt.bindString(1, "US"); stmt.execute();
对于Android中准备好的SQLite语句,有SQLiteStatement 。 准备好的语句可以帮助您加速性能(特别是对于需要多次执行的语句),还可以帮助避免注入攻击。 请参阅本文以获取有关预准备语句的一般性讨论。
SQLiteStatement
旨在用于不返回多个值的SQL语句。 (这意味着你不会在大多数查询中使用它们。)下面是一些例子:
创build一个表
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()
。 当然,你不想总是在每一行input相同的东西。 为此,您可以使用绑定 。
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); // These match to the two question marks in the sql string statement.bindString(2, stringValue); long rowId = statement.executeInsert();
通常,当您想要快速重复某些操作(如INSERT)时,通常会使用准备好的语句。 准备好的语句使得SQL语句不必每次都被parsing和编译。 通过使用交易,您可以加快速度。 这允许一次应用所有更改。 这里是一个例子:
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(); }
查看这些链接,获取关于事务的更多信息,并加速数据库插入。
- primefaces提交在SQLite (深入的解释,请参阅第3部分)
- 数据库事务
- Android的SQLite批量插入和更新的例子
- 带有INSERT准备语句的Android SQLite事务示例
- 在Android上加载你的SQLite插件
- https://stackoverflow.com/a/8163179/3681880
更新行
这是一个基本的例子。 您也可以应用上面的部分的概念。
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 。
询问
通常当你运行一个查询时,你想要得到一个有很多行的游标。 不过,这不是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"));
如果你想要更完整的一个,请参阅这个片段Genscripts 。 请注意,这是一个参数化的SQL查询,所以本质上它是一个准备好的语句。
jasonhudgins的例子将无法正常工作。 你不能用stmt.execute()
执行一个查询并返回一个值(或者一个Cursor
)。
您只能预编译根本不返回任何行的语句(如插入或创build表语句)或单个行和列(并使用simpleQueryForLong()
或simpleQueryForString()
)。
要获得游标,不能使用compiledStatement。 但是,如果你想使用完整准备的SQL语句,我推荐使用jbaez的方法…使用db.rawQuery()
而不是db.query()
。