SQLiteDatabase 使用替换函数更新
SQLiteDatabase update using replace function
我想使用 SQLiteDatabase 使用 SQLite replace
函数和 LIMIT
执行更新,其中 SQL像这样:
UPDATE tbl SET tel = replace(tel, '0501', '0502') where tel in (SELECT tel FROM tbl WHERE tel LIKE '0501%' ORDER BY tel LIMIT 100);
这看起来不错 SQL 就像这个 fiddle。
因此更新的签名类似于:
db.update(String table, ContentValues values, String whereClause, String[] whereArgs)
所以我尝试使用 ContentValues
作为一个疯狂的猜测,例如:
ContentValues cv = new ContentValues();
cv.put("tel","replace( tel, '0511', '0513' )");
int result = db.update(tableName,cv,whereClause,null);
这并没有执行 REPLACE
函数,而是按字面意思执行。
那么如何使用REPLACE
函数使用update
就是个问题
我需要知道有多少行受到影响。
编辑:我将查询更改为每个评论 link 的有效 SQLite 语法,现在看到它是有效的但是 REPLACE
没有被评估。
便利方法在封闭值方面确实有限制。
您可以改用 execSQL
方法(参见代码 re rawQuery),例如:-
public long alterRows(String from, String to, int limit) {
long rv = 0;
String[] args = new String[]{from,to,from,String.valueOf(limit)};
String sql = "UPDATE " + TB_TBL +
" SET " + COL_TBL_TEL + " = replace(" + COL_TBL_TEL + ",?,?) " + //<<<<IGNORE EXPRESSION EXPECTED
" WHERE rowid IN (" +
"SELECT rowid FROM " + TB_TBL +
" WHERE " + COL_TBL_TEL + "=? " +
"ORDER BY " + COL_TBL_TEL +
" LIMIT ?" +
");" ;
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL(sql,args);
//mDB.rawQuery(sqlxxx,args); //<<<< only does 1 update not 2
//Ascertain the number of updates
Cursor csr = db.rawQuery("SELECT changes()",null);
if (csr.moveToFirst()) {
rv = csr.getLong(0);
}
csr.close();
Log.d("Updates","Number of updates = " + String.valueOf(rv)); //<<<< LOG number of updates
return rv;
}
可以这样称呼:-
SO50378333DBHelper mDBHlpr = new SO50378333DBHelper(this);
mDBHlpr.alterRows("0501","0502",2);
- 其中
SO50378333DBHelper
是上述代码所在的 DatabaseHelper(为方便起见而命名)。
用于测试的示例
以下是用于测试的完整代码。
首先是数据库助手SO50378333DBHelper.java
public class SO50378333DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "so50378333";
public static final int DBVERSION = 1;
public static final String TB_TBL = "tbl";
public static final String COL_TBL_TEL = "tel";
SQLiteDatabase mDB;
public SO50378333DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
String crt_tbl = "CREATE TABLE IF NOT EXISTS " + TB_TBL +
"(" +
COL_TBL_TEL + " TEXT" +
")";
db.execSQL(crt_tbl);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void loadTBL() {
ContentValues cv = new ContentValues();
mDB.beginTransaction();
mDB.delete(TB_TBL,null,null);
for (int i = 0; i < 1000; i++) {
cv.clear();
if ( i % 4 == 0) {
cv.put(COL_TBL_TEL,"0501");
} else {
cv.put(COL_TBL_TEL,"0504");
}
mDB.insert(TB_TBL,null,cv);
}
String sql = "SELECT sqlite_version() AS v";
Cursor csr = mDB.rawQuery(sql,null);
if (csr.moveToFirst()) {
Log.d("SQLite VERSION","Version is " + csr.getString(0));
}
mDB.setTransactionSuccessful();
mDB.endTransaction();
}
public long alterRows(String from, String to, int limit) {
long rv = 0;
String[] args = new String[]{from,to,from,String.valueOf(limit)};
String sql = "UPDATE " + TB_TBL +
" SET " + COL_TBL_TEL + " = replace(" + COL_TBL_TEL + ",?,?) " + //<<<<IGNORE EXPRESSION EXPECTED
" WHERE rowid IN (" +
"SELECT rowid FROM " + TB_TBL +
" WHERE " + COL_TBL_TEL + "=? " +
"ORDER BY " + COL_TBL_TEL +
" LIMIT ?" +
");" ;
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL(sql,args);
//mDB.rawQuery(sqlxxx,args); //<<<< only does 1 update not 2
//Ascertain the number of updates
Cursor csr = db.rawQuery("SELECT changes()",null);
if (csr.moveToFirst()) {
rv = csr.getLong(0);
}
csr.close();
Log.d("Updates","Number of updates = " + String.valueOf(rv)); //<<<< LOG number of updates
return rv;
}
}
- 查看评论//<<<<
rawQuery
实际上并没有更新任何行,即使 changes() 函数指示它更新了 1 而不是 2。这可能是因为它报告了由于 rawQuery 而导致的最后一个 INSERT未执行任何更新。
rawQuery
不会更新,因为直到访问结果(游标)(例如 moveToFirst())(实际上不是),它才会执行它的工作。
第二个 activity 中的调用代码 (MainActivity.java)
SO50378333DBHelper mDBHlpr = new SO50378333DBHelper(this);
mDBHlpr.loadTBL();
mDBHlpr.alterRows("0501","0502",2);
- 注意对
loadTBL
的调用将数据加载到 table 中(在这样做之前删除所有行)。插入 1000 行,4 的每个 first 行将是 "0501" (250) 所有其他行 (750) 将是 "0504"
上面日志中的结果:-
05-16 23:19:31.554 2622-2622/? D/SQLite VERSION: Version is 3.7.11
05-16 23:19:31.558 2622-2622/? D/Updates: Number of updates = 2
我想使用 SQLiteDatabase 使用 SQLite replace
函数和 LIMIT
执行更新,其中 SQL像这样:
UPDATE tbl SET tel = replace(tel, '0501', '0502') where tel in (SELECT tel FROM tbl WHERE tel LIKE '0501%' ORDER BY tel LIMIT 100);
这看起来不错 SQL 就像这个 fiddle。
因此更新的签名类似于:
db.update(String table, ContentValues values, String whereClause, String[] whereArgs)
所以我尝试使用 ContentValues
作为一个疯狂的猜测,例如:
ContentValues cv = new ContentValues();
cv.put("tel","replace( tel, '0511', '0513' )");
int result = db.update(tableName,cv,whereClause,null);
这并没有执行 REPLACE
函数,而是按字面意思执行。
那么如何使用REPLACE
函数使用update
就是个问题
我需要知道有多少行受到影响。
编辑:我将查询更改为每个评论 link 的有效 SQLite 语法,现在看到它是有效的但是 REPLACE
没有被评估。
便利方法在封闭值方面确实有限制。
您可以改用 execSQL
方法(参见代码 re rawQuery),例如:-
public long alterRows(String from, String to, int limit) {
long rv = 0;
String[] args = new String[]{from,to,from,String.valueOf(limit)};
String sql = "UPDATE " + TB_TBL +
" SET " + COL_TBL_TEL + " = replace(" + COL_TBL_TEL + ",?,?) " + //<<<<IGNORE EXPRESSION EXPECTED
" WHERE rowid IN (" +
"SELECT rowid FROM " + TB_TBL +
" WHERE " + COL_TBL_TEL + "=? " +
"ORDER BY " + COL_TBL_TEL +
" LIMIT ?" +
");" ;
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL(sql,args);
//mDB.rawQuery(sqlxxx,args); //<<<< only does 1 update not 2
//Ascertain the number of updates
Cursor csr = db.rawQuery("SELECT changes()",null);
if (csr.moveToFirst()) {
rv = csr.getLong(0);
}
csr.close();
Log.d("Updates","Number of updates = " + String.valueOf(rv)); //<<<< LOG number of updates
return rv;
}
可以这样称呼:-
SO50378333DBHelper mDBHlpr = new SO50378333DBHelper(this);
mDBHlpr.alterRows("0501","0502",2);
- 其中
SO50378333DBHelper
是上述代码所在的 DatabaseHelper(为方便起见而命名)。
用于测试的示例
以下是用于测试的完整代码。
首先是数据库助手SO50378333DBHelper.java
public class SO50378333DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "so50378333";
public static final int DBVERSION = 1;
public static final String TB_TBL = "tbl";
public static final String COL_TBL_TEL = "tel";
SQLiteDatabase mDB;
public SO50378333DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
String crt_tbl = "CREATE TABLE IF NOT EXISTS " + TB_TBL +
"(" +
COL_TBL_TEL + " TEXT" +
")";
db.execSQL(crt_tbl);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void loadTBL() {
ContentValues cv = new ContentValues();
mDB.beginTransaction();
mDB.delete(TB_TBL,null,null);
for (int i = 0; i < 1000; i++) {
cv.clear();
if ( i % 4 == 0) {
cv.put(COL_TBL_TEL,"0501");
} else {
cv.put(COL_TBL_TEL,"0504");
}
mDB.insert(TB_TBL,null,cv);
}
String sql = "SELECT sqlite_version() AS v";
Cursor csr = mDB.rawQuery(sql,null);
if (csr.moveToFirst()) {
Log.d("SQLite VERSION","Version is " + csr.getString(0));
}
mDB.setTransactionSuccessful();
mDB.endTransaction();
}
public long alterRows(String from, String to, int limit) {
long rv = 0;
String[] args = new String[]{from,to,from,String.valueOf(limit)};
String sql = "UPDATE " + TB_TBL +
" SET " + COL_TBL_TEL + " = replace(" + COL_TBL_TEL + ",?,?) " + //<<<<IGNORE EXPRESSION EXPECTED
" WHERE rowid IN (" +
"SELECT rowid FROM " + TB_TBL +
" WHERE " + COL_TBL_TEL + "=? " +
"ORDER BY " + COL_TBL_TEL +
" LIMIT ?" +
");" ;
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL(sql,args);
//mDB.rawQuery(sqlxxx,args); //<<<< only does 1 update not 2
//Ascertain the number of updates
Cursor csr = db.rawQuery("SELECT changes()",null);
if (csr.moveToFirst()) {
rv = csr.getLong(0);
}
csr.close();
Log.d("Updates","Number of updates = " + String.valueOf(rv)); //<<<< LOG number of updates
return rv;
}
}
- 查看评论//<<<<
rawQuery
实际上并没有更新任何行,即使 changes() 函数指示它更新了 1 而不是 2。这可能是因为它报告了由于 rawQuery 而导致的最后一个 INSERT未执行任何更新。rawQuery
不会更新,因为直到访问结果(游标)(例如 moveToFirst())(实际上不是),它才会执行它的工作。
第二个 activity 中的调用代码 (MainActivity.java)
SO50378333DBHelper mDBHlpr = new SO50378333DBHelper(this);
mDBHlpr.loadTBL();
mDBHlpr.alterRows("0501","0502",2);
- 注意对
loadTBL
的调用将数据加载到 table 中(在这样做之前删除所有行)。插入 1000 行,4 的每个 first 行将是 "0501" (250) 所有其他行 (750) 将是 "0504"
上面日志中的结果:-
05-16 23:19:31.554 2622-2622/? D/SQLite VERSION: Version is 3.7.11 05-16 23:19:31.558 2622-2622/? D/Updates: Number of updates = 2