使用replace函数更新SQLiteDatabase

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用replace函数更新SQLiteDatabase相关的知识,希望对你有一定的参考价值。

我想使用SQLiteDatabase使用带有replace的SQLite 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函数是个问题。

我需要知道有多少行受到影响。

编辑:我将查询更改为每个评论链接的有效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(以我的方便命名),其中存在上述代码。

用于测试的示例

以下是用于测试此内容的完整代码。

首先是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.这很可能是因为它报告了最后一次INSERT,因为rawQuery没有执行任何更新。
  • rawQuery不会更新,因为直到结果(光标)被访问(例如moveToFirst())(它不是),它才能完成它的工作。

第二个在活动中调用代码(MainActivity.java)

    SO50378333DBHelper mDBHlpr = new SO50378333DBHelper(this);
    mDBHlpr.loadTBL();
    mDBHlpr.alterRows("0501","0502",2);
  • 请注意,对loadTBL的调用会将数据加载到表中(在执行此操作之前删除所有行)。插入1000行,每4行的第一行将为“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

以上是关于使用replace函数更新SQLiteDatabase的主要内容,如果未能解决你的问题,请参考以下文章

Linux 内核 内存管理RCU 机制 ④ ( RCU 模式下更新链表项 list_replace_rcu 函数 | 链表操作时使用 smp_wmb() 函数保证代码执行顺序 )

sql server replace 函数使用方法

关于 CREATE OR REPLACE 和动态更新数据库的问题

在 text 或 ntext 数据类型上替代 REPLACE

在 text 或 ntext 数据类型上替代 REPLACE

从回调中更新 preg_replace_callback 之外的变量 [重复]