【问题标题】:SQLite: Preventing Duplicate RowsSQLite:防止重复行
【发布时间】:2015-03-28 02:09:47
【问题描述】:
CREATE TABLE Permission ( 
    permissionID INTEGER PRIMARY KEY UNIQUE,
    user         INTEGER
    location     INTEGER 
);

我不想让用户或位置成为UNIQUE,因为我可以有多个用户包含相同数据的行,或者多个位置包含相同数据的行。我只是想避免让用户和位置都具有一些价值,因为该行重复任意次数。

例如:没关系

permissionID user location
--------------------------
      1        1     2
      2        2     2
      3        2     1

但这不行:

permissionID user location
--------------------------
      1        1     2
      2        1     2

因为已经存在用户 = 1 和位置 = 2 的行。

如何避免重复?

【问题讨论】:

    标签: sql database sqlite


    【解决方案1】:

    声明对(用户、位置)的唯一约束。

    CREATE TABLE Permission (
        permissionID integer primary key,
        user integer not null,
        location integer not null,
        unique (user, location)
    );
    
    sqlite> 插入权限(用户、位置)值(1、2); sqlite> 插入权限(用户、位置)值(1、2); 错误:唯一约束失败:Permission.user、Permission.location

    【讨论】:

      【解决方案2】:

      第一个选项是在userlocation 列上创建unique constraint,这将避免重复。

      Create unique index permission_user_location  on permission (user,location);
      

      否则,如果表中已有重复行,则需要删除重复行并创建unique constraint

      要删除重复行,请使用此查询

      DELETE
      FROM Permission 
      WHERE NOT EXISTS 
      (
      select 1 from 
      (
      select min(permissionID) as permissionID, user, location
      From Permission A
      Group by user, location
      ) B
      Where B.permissionID = Permission.permissionID
      AND   B.user = Permission.User
      AND   B.location = Permission.location 
      )
      

      【讨论】:

        【解决方案3】:
        CREATE TABLE Permission ( 
            permissionID INTEGER PRIMARY KEY UNIQUE,
            user         INTEGER,
            location     INTEGER 
        );
        CREATE UNIQUE INDEX user_location ON Permission (user,location);
        

        【讨论】:

          【解决方案4】:

          您本质上想要做的是使用户和位置的组合在您的桌子上独一无二。 有几个选项可以实现这一点,我将按照您应该考虑的顺序描述这些选项,因为前者比后者更自然。

          选项 1:在您的表中具有唯一约束

          你可以把你想要的约束直接放在你的表中:

          CREATE TABLE Permission (
              permissionID INTEGER PRIMARY KEY UNIQUE,
              user         INTEGER,
              location     INTEGER 
              unique (user, location)
          );
          

          这是表达您的要求的最自然的选择。需要注意的是,在现有表上添加和删除此选项并不容易。有关如何将此选项添加到现有表的信息,请参阅本文的附件 2。

          如果您现在尝试在表中插入重复条目,您会得到以下结果:

          sqlite> insert into Permission (user, location) values (1, 2);
          Error: UNIQUE constraint failed: Permission.user, Permission.location
          

          选项 2:创建唯一索引

          也可以创建auniqe索引

          CREATE TABLE Permission ( 
              permissionID INTEGER PRIMARY KEY UNIQUE,
              user         INTEGER,
              location     INTEGER 
          );
          CREATE UNIQUE INDEX user_location ON Permission (user,location);
          

          如果您尝试使用此选项插入重复条目,则会收到与第一个选项完全相同的错误消息:

          sqlite> insert into Permission (user, location) values (1, 2);
          Error: UNIQUE constraint failed: Permission.user, Permission.location
          

          您可能会询问此选项与第一个选项 and so have many others 之间的区别。正如sqlite documentation 解释的那样,在内部它可能以完全相同的方式实现。归根结底,从表中添加和删除索引比在表上添加和删除唯一约束要容易得多。

          选项 3:使用触发器

          为了完整起见,也可以使用触发器来防止插入重复项,尽管我很难想象为什么您应该更喜欢这个选项。这是对INSERT 做出反应的最通用方式,您的示例可能如下所示:

          CREATE TRIGGER avoid_duplicate_user_locations
             BEFORE INSERT
             ON Permission
             when exists (select * from Permission where user = new.user and location = new.location)
          BEGIN
          SELECT
               RAISE (ABORT,'duplicate entry');
          END;
          

          如果您尝试使用此选项插入重复条目,您将遇到您在触发器中指定的错误消息:

          sqlite> insert into Permission (user, location) values (1, 2);
          Error: duplicate entry
          

          附件 1:删除现有重复项

          如果您的表中已有重复项,以下代码将帮助您删除它们。如果你想应用第一个或第二个选项,你必须这样做。

          DELETE FROM Permission 
            WHERE permissionID NOT IN 
              (SELECT MIN(permissionID) FROM Permission GROUP BY user,location );
          

          附件 2:向表中添加唯一约束

          如果您已经为没有UNIQUE 约束的表创建了架构,这里有一个如何添加它的秘诀。

          CREATE TABLE Permission2 (
              permissionID INTEGER PRIMARY KEY UNIQUE,
              user         INTEGER,
              location     INTEGER, 
              unique (user, location)
          );
          
          INSERT INTO Permission2
          SELECT *
          FROM Permission;
          
          DROP Table Permission;
          
          ALTER TABLE Permission2
          RENAME TO Permission;
          

          【讨论】:

          • 这是最有用的答案。非常感谢
          猜你喜欢
          • 2010-11-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-14
          • 2020-08-12
          • 2016-01-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多