【问题标题】:Blackberry SQLite mass delete best practice黑莓 SQLite 批量删除最佳实践
【发布时间】:2012-01-19 22:15:34
【问题描述】:

我有一个 SQLite 数据库,我需要定期从中删除记录。在性能方面,这样做的最佳方法是什么。我有一系列独特的 PK id。我想出了两种方法:

使用准备好的语句

    int[] ids = {1,2,3,4,5}; //example only, will be built elsewhere
    Database db = null;
    try {
        db = DataConnection.getInstance(); //my class to get the connection instance
        db.beginTransaction();
        Statement st = db.createStatement("DELETE FROM myTable WHERE id = ?");
        st.prepare();
        for (int i=0;i<ids.length;i++) {
            st.bind(1, ids[i]);
            st.execute();
            st.reset();
        }
        db.commitTransaction();
    } catch (FileIOException e) {
        e.printStackTrace();
    } catch (DatabaseException e) {
        e.printStackTrace();
    }

或者使用'in'关键字

    int[] ids = {1,2,3,4,5}; //example only, will be built elsewhere
    Database db = null;
    try {
        db = DataConnection.getInstance();
        //Util.JoinArray(int[] ids,char delim, char prepend, char postpend) returns a String of the ids separated by delim with prepend at the front and postpend at the end
        Statement st = db.createStatement("DELETE FROM myTable WHERE id IN " + Util.joinArray(ids,',','(',')'));
        st.prepare();
    } catch (FileIOException e) {
        e.printStackTrace();
    } catch (DatabaseException e) {
        e.printStackTrace();
    }

【问题讨论】:

    标签: sqlite blackberry


    【解决方案1】:

    理想的方法是两者的结合:所有 ID 的预准备语句。

    因此,避免 SQL 注入并使用这样的方法(在伪代码中):

    query = "DELETE FROM myTable WHERE id IN (";
    for (int i = 0; i < ids.count; i++)
        query.Append("?,");
    query.DropLast(); //Remove the last comma
    query.Append(")");
    st = db.createStatement(query);
    st.prepare();
    for (int i = 0; i < ids.count; i++)
        st.bind(i+1, ids[i]);
    

    性能方面,这可能会更好,因为数据库将在所有删除后重新平衡索引。不过,在事务中工作并在所有单个删除之后提交一次基本上是相同的。我建议的方法只会更安全。

    正如在 SO 上经常讨论的那样,SQLite 的性能在各种标准上差别很大,即结构、行数、页面大小等。SQLite 没有通用的“在所有情况下都更快”的方法。您的里程会有所不同。

    【讨论】:

    • 我以前在 MySQL 和 servlet 中使用过这种方法。构建 (?,?...) 和绑定而不是仅仅在该字符串中构建 id 似乎是额外的工作。它来自 int[] 所以我认为 SQL 注入不是问题。如果我有一个字符串 PK,我会这样做。
    • @kyle 老实说,自从我匆忙(羞愧地)拼凑出我称之为“SQL 注入引擎”的东西后,我有点偏执,但是是的,我想这是多余的用整数来做。
    • +1。但是 SQLite IN 子句最多需要 999 个参数。 sqlite.org/limits.html
    • @MisterSmith 在这些范围内,要么使用子查询,要么循环通过 999 个批次。但真的要考虑使用该子查询!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    • 2011-06-28
    • 1970-01-01
    相关资源
    最近更新 更多