SQLite:防止重复行

use*_*798 12 sql database sqlite

CREATE TABLE Permission ( 
    permissionID INTEGER PRIMARY KEY UNIQUE,
    user         INTEGER
    location     INTEGER 
);
Run Code Online (Sandbox Code Playgroud)

我不希望有用户或位置,UNIQUE因为我可以有多行,用户包含相同的数据,或多行,其中包含相同数据的位置.我只是想避免让用户和位置都有一些值,该行重复任意次.

例如:这没关系

permissionID user location
--------------------------
      1        1     2
      2        2     2
      3        2     1
Run Code Online (Sandbox Code Playgroud)

但这不好

permissionID user location
--------------------------
      1        1     2
      2        1     2
Run Code Online (Sandbox Code Playgroud)

因为已经存在一行user = 1和location = 2.

我怎样才能避免重复?

Mik*_*ll' 19

在(用户,位置)上声明唯一约束.

CREATE TABLE Permission (
    permissionID integer primary key,
    user integer not null,
    location integer not null,
    unique (user, location)
);
Run Code Online (Sandbox Code Playgroud)
sqlite> insert into Permission (user, location) values (1, 2);
sqlite> insert into Permission (user, location) values (1, 2);
Error: UNIQUE constraint failed: Permission.user, Permission.location


Mar*_*hen 7

您本质上想要做的是使用户和位置的组合在整个表中唯一。有多种选择可以实现这一目标,我将按照您考虑的顺序描述这些选项,因为前一种选择比后者更自然。

选项 1:在表中设置唯一约束

您可以将所需的约束直接放入表中:

CREATE TABLE Permission (
    permissionID INTEGER PRIMARY KEY UNIQUE,
    user         INTEGER,
    location     INTEGER 
    unique (user, location)
);
Run Code Online (Sandbox Code Playgroud)

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

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

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

选项 2:创建唯一索引

也可以创建auniqe索引

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

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

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

您可能会问这个选项与第一个选项之间的区别,许多其他选项也是如此。正如sqlite 文档所解释的,在内部它可能以完全相同的方式实现。归根结底,在表中添加和删除索引比在表上添加和删除唯一约束要容易得多。

选项 3:使用触发器

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

CREATE TABLE Permission ( 
    permissionID INTEGER PRIMARY KEY UNIQUE,
    user         INTEGER,
    location     INTEGER 
);
CREATE UNIQUE INDEX user_location ON Permission (user,location);
Run Code Online (Sandbox Code Playgroud)

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

sqlite> insert into Permission (user, location) values (1, 2);
Error: duplicate entry
Run Code Online (Sandbox Code Playgroud)

附件 1:删除现有重复项

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

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

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

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

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;
Run Code Online (Sandbox Code Playgroud)