【问题标题】:Create Unique Index not helping to stop duplicates创建唯一索引无助于阻止重复
【发布时间】:2014-10-02 08:51:09
【问题描述】:

我有一个名为 details 的主数据库表,其中包含三个感兴趣的列 -

_id | Name | BirthDate | xx | xx | xx | ...

我使用以下语句在上表上创建一个唯一索引:

CREATE UNIQUE INDEX _id ON Details (Name, BirthDate)

上面的目的是停止表中的重复条目,我不希望任何名字和出生日期相同。 (虽然我不确定是否这样做,但我尝试插入具有相同出生日期和姓名的新记录,我发现之前具有相同凭据的现有记录已被删除,并且在最后插入了这个新记录) - 但是这是在我介绍以下内容之前并非如此:

我有一个单独的表格,名为 Notifications:

| _id | NotificationFor | DateToNotify | IsExtraordinary | NotificationData | NotificationDateFor | TypeNotification | RadioType | FriendsName | PrimaryId |

以上两个表是映射的:Details表中的_id是Notifications表中的PrimaryId

为 Details 表中的每个 _id(记录)计算四条记录,并将它们全部插入到 Notifications 表中。

现在这里的问题是我不想在我的任何表中重复记录,所以我在 Notifications 表上放置了一个唯一索引,如下所示:

CREATE UNIQUE INDEX _id ON Notifications (NotificationFor, DateToNotify, IsExtraordinary,NotificationData,NotificationDateFor,TypeNotification,RadioType,FriendsName,PrimaryId);

我收到以下错误:

10-02 14:16:31.439: E/AndroidRuntime(31743): FATAL EXCEPTION: main
10-02 14:16:31.439: E/AndroidRuntime(31743): java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx.xxx.xxx}: android.database.sqlite.SQLiteException: index _id already exists (code 1): , while compiling: CREATE UNIQUE INDEX _id ON Notifications (NotificationFor, DateToNotify, IsExtraordinary,NotificationData,NotificationDateFor,TypeNotification,RadioType,FriendsName,PrimaryId );

在我的 DBAdapter 中,我正在执行如下代码:

db.execSQL(uniqueDetails); 
db.execSQL(uniqueNotifications);

我将 uniqueNotifications 查询更改为:

CREATE UNIQUE INDEX NotificationDateFor ON Notifications (NotificationFor, DateToNotify, IsExtraordinary,NotificationData,NotificationDateFor,TypeNotification,RadioType,FriendsName,PrimaryId );

现在我没有收到错误消息,但我在通知表中看到了重复项。任何提示我可以如何改进上述内容并使其发挥作用?

为了增强上述功能,我从文件中读取记录并将它们插入表中我首先计算我的数据并将其插入到详细信息中,在这种情况下,在 for 循环中我没有在通知上使用 UNIQUE - 我在详细信息上使用 UNIQUE工作正常。但是,如果我遇到来自 Details 的重复项,我想停止 for 循环的迭代并跳转到下一次迭代,因为我不希望将重复项输入到 Notifications 表中 - 是否存在 UNIQUE 查询的返回类型 - 如果执行在详细信息上,我发现了一个重复项,我想将循环切换到下一次迭代 - 跳过有关 Notifications 表的插入语句。抱歉,我知道我不善于解释。

编辑:

我在表格的末尾添加了以下记录,而在插入之前,我以原始形式保存了这条记录 - 现在我看不到旧的记录,但新的记录已插入到最后:

详细信息表 - 我无法复制这两个表,因为其中一个已被删除。

Notifications 表中的对应方:(顶部名为 Tom Hanks 的记录)

同一张表底部不同_id重复的记录:

下面我重现了详细信息表,如果您观察到记录号 90 不再存在 - 因为它可能在插入“相同值”记录之前被删除:(_idPrimaryId 值已映射)

编辑:

以下是我的插入语句(详见表):

public void insert(String birthDate, String name, String daysOld, String hoursOld, String uRi, String minutesOld, String months, String seconds, String timestamP, String weeks, String years, String isAdhoc){
        //  InsertHelper ih = new InsertHelper(db, "columnTable");

        String INUP= "INSERT OR REPLACE INTO Details (BirthDate, Name, isAdhoc, daysOld, hoursOld, imageUri, minutesOld, monthsOld, secondsOld, timestamp, weeksOld, yearsOld) " +
                "values ("+"'"+birthDate+"'"+","+"'"+name+"'"+","+"'"+isAdhoc+"'"+","+"'"+daysOld+"'"+","+"'"+ hoursOld+"'"+","+"'"+ uRi+"'"+","+"'"+minutesOld+"'"+","+"'"+ months+"'"+","+"'"+ seconds+"'"+","+"'"+timestamP+"'"+","+"'"+weeks+"'"+","+"'"+years+"'"+");";  
        mDb.execSQL(INUP);
    }

我认为上面的 INSERT OR REPLACE 可能会造成问题。

【问题讨论】:

  • 听起来您真正想要的是主键/外键约束,而不是索引......或者我误读/误解了这个问题。索引有助于加快数据检索。
  • 不,我有一个主键 - 我只是不想在我的表中重复 详细信息表中的一条记录(具有唯一的名称和出生日期) - 该记录还有四个计算并插入到通知中的记录 - 我也不想在这里重复。
  • 在两行中显示您认为应该作为重复项被拒绝的值。
  • 好的,我正在更新问题

标签: java android sql sqlite unique-index


【解决方案1】:

使用唯一约束来强制执行唯一值。

private static final String VERSION_60_CREATE_TABLE = "CREATE TABLE "
        + TABLE_MARKERS + "(" + KEY_ID + " INTEGER PRIMARY KEY,"
        + KEY_MARKER_LOCATION_ID + " INTEGER," + KEY_MARKER_IMAGE_ID
        + " INTEGER DEFAULT -1," + KEY_MARKER_IMAGE_PATH + " TEXT,"
        + KEY_MARKER_SNIPPET + " TEXT," + KEY_MARKER_TITLE + " TEXT,"
        + " FOREIGN KEY(" + KEY_MARKER_LOCATION_ID + ") REFERENCES "
        + TABLE_LOCATIONS + "(" + KEY_ID + ")," + " CONSTRAINT UNQ_"
        + KEY_MARKER_IMAGE_ID + " UNIQUE (" + KEY_MARKER_IMAGE_ID
        + ") ON CONFLICT ABORT)";

最佳实践:在代码中为约束指定一个含义全名。上面的示例使用 UNQ_ 与列名连接作为约束名称。对于 db gui 设计器,请使用设计器的约束名称。

【讨论】:

  • 但是我在示例代码中使用了唯一约束。但是,当我使用 INSERT OR REPLACE 时,我的旧行被删除并插入了一个新行。如果我知道返回类型告诉我最后一个插入是否找到重复项的方式会很有帮助。
  • 索引没有创建,因为您已经有重复的行。您必须从 count(key)>1 按键分组的表中运行某种形式的删除。如果您想要中止,则默认值是替换,您必须重新创建表,因为 sqlite 不支持使用更改表添加约束。但第一次摆脱你的重复。
  • 这个项目没有投入生产,所以我不必担心删除重复项 - 我重新开始。我只是将 INSERT OR REPLACE 更改为 INSERT 并且它可以工作。遇到重复项时会引发异常。现在它默默地死了,但我想捕捉这个异常并向用户展示一个对话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 2014-12-29
  • 2015-03-22
  • 1970-01-01
  • 2019-12-04
  • 2018-06-19
  • 1970-01-01
相关资源
最近更新 更多