如何在Android的SQlite中使用准备好的语句? 建立表格 插入值 更新行 删除行 询问

最后发布: 2009-01-11 18:38:27


问题

如何在Android的SQlite中使用准备好的语句?

android sqlite prepared-statement
回答

对于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();

通常,您将运行SQLiteDatabasequery()方法来获取游标。

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);

有关查询的更多详细信息,请参见此答案


回答

我一直在Android中使用准备好的语句,这很简单:

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


回答

如果要让游标返回,则可以考虑如下所示:

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"));

如果您想要更完整的摘要 ,请参阅此摘要 请注意,这是一个参数化的SQL查询,因此,实质上,这是一个准备好的语句。


回答

jasonhudgins示例不起作用。 您无法使用stmt.execute()执行查询并获取值(或Cursor )。

您只能预编译完全不返回任何行的语句(例如,insert或create table语句)或单个行和列(并使用simpleQueryForLong()simpleQueryForString() )。


回答

要获取游标,不能使用compiledStatement。 但是,如果要使用完整的SQL语句,我建议改写jbaez的方法...使用db.rawQuery()代替db.query()