如何在SQLite中有效地批量更新项目的标签列表?

时间:2012-01-01 22:06:06

标签: java android sqlite

我基本上想在SQLite中进行补充集操作但不确定如何。

假设我在内存中有这样一个项目的标签列表:

"red", "blue", "green", "yellow"

并且数据库具有与同一项目关联的这些标记:

"red", "orange", "purple"

我想要的是让数据库反映内存中的状态。我需要:

  1. 删除与数据库中项目中内存不存在的标记的关系。删除“organge”和“purple。”。
  2. 添加我没有在数据库中但在内存中执行的标记关系。添加“蓝色”,“绿色”和“黄色”。
  3. 我可以简单地获取现有标签的整个列表,并使用Java(在Android上)执行SQL之外的操作,但这可能是一个巨大的列表,我在移动设备上执行此操作。

    我还可以删除该项目的所有现有标记关系,然后将其添加到内存中,但这可能会添加许多已经存在的关系并且看起来像是不必要的工作。

    我基本上有以下表格:

    项目

    id, int primary key autoincrement not null
    name, text
    

    标签

    id, int primary key autoincrement not null
    name text
    

    tagged_items

    id, int primary key autoincrement not null
    tag_id, int
    item_id, int
    

2 个答案:

答案 0 :(得分:1)

  

假设我在内存中有这样一个项目的标签列表......并且数据库中有这些标签与同一项目相关联

一种方法是让你的内存中表示同时保持当前状态和最后持久状态。

然后,当需要更新数据库时,通过执行{{3},您确切地知道需要从tagged_items插入和删除(并且可能插入tags)的内容。 }。

这假定你要么:

  • 删除tags表的无关整数主键,因为标记应该是唯一的,或者
  • 您在内存中保留了标记及其ID

您可以通过子SELECT仅在内存中保留标记,从标记文本中导出id,但我个人只是从id列中取出tags列。 {1}}。

当您执行数据库I / O时,将其全部包装在事务中,不仅因为逻辑上工作应该成功还是整体失败,而是为了提高Android上SQLite的性能。

另一种方法是让你摆脱直接的SQLite访问并切换到可能为你处理这类事情的set difference operations之类的东西。我没有亲自使用它。

答案 1 :(得分:0)

我会按" item_id + tag_id"对两个列表进行排序并确保数据库选择仅影响内存列表中的那些itemID。

select item_id, tag_id from tagged_items 
  where item_id in (... list of  memory item_id ...) 
  order by item_id, tag_id

然后

  • 推进较小的列表项或
  • 如果两个列表项均相等,则
  • 或提前两个列表项

示例:

假设这些tag_ids:"红色" = 1,"蓝色" = 2,"绿色" = 3,"黄色" = 4 ,"橙" = 5,"紫" = 6。 示例数据的当前item_id是97

  • mem 97,1-red db 97,1-red
    • 两个相同
    • no db action
    • 推进两者
  • mem 97,2-blue db 97,5-orange
    • mem<分贝
    • 插入97,2-blue
    • advance mem
  • mem 97,3-green db 97,5-orange
    • mem<分贝
    • 插入97,3-green
    • advance mem
  • mem 97,4-yello db 97,5-orange
    • mem<分贝
    • 插入97,4-yello
    • advance mem
  • mem 98,4-yello db 97,5-orange
    • mem> db(下一个mem项目,97,5-orange不再在DB中)
    • 删除97,5-orange
    • advance db