What you essentially want to do is to make the combination of user and location unique across you table.
There are several options to achieve that and I will describe these options in the order you should consider them, as the former options are more natural than the latter.
Option 1: Have a unique constraint in your table
You can put the constraint you want directly in your table:
CREATE TABLE Permission (
permissionID INTEGER PRIMARY KEY UNIQUE,
user INTEGER,
location INTEGER
unique (user, location)
);
This is the most natural option to express your requirement. The caveat is that it is not so easy to add and remove this option on an existing table. See the Annex 2 of this post on how to add this option to an existing table.
If you now try to insert a duplicate entry into the table you get the following result:
sqlite> insert into Permission (user, location) values (1, 2);
Error: UNIQUE constraint failed: Permission.user, Permission.location
Option 2: Create a unique index
It is also possible to create auniqe index
CREATE TABLE Permission (
permissionID INTEGER PRIMARY KEY UNIQUE,
user INTEGER,
location INTEGER
);
CREATE UNIQUE INDEX user_location ON Permission (user,location);
If you try to insert a duplicate entry with this option you get the exact same error message as in the first option:
sqlite> insert into Permission (user, location) values (1, 2);
Error: UNIQUE constraint failed: Permission.user, Permission.location
You might ask about the difference between this option and the first one, and so have many others . As the sqlite documentation explains, internally it is probably implemented in the exact same way. It really boils down to the fact, that it is much easier to add and drop an index from a table than to add and remove a unique constraint on a table.
Option 3: Use a trigger
For the sake of completeness, it is also possible to use a trigger to prevent duplicates to be inserted, albeit I hardly can imagine a reason why you should prefer this option. It is the most general way to react on an INSERT and it could look like this for your example:
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;
If you try to insert a duplicate entry with this option, you will run into the error message you specified in the trigger:
sqlite> insert into Permission (user, location) values (1, 2);
Error: duplicate entry
Annex 1: Removing existing Duplicates
If you already have duplicates in your table, the following code will help you you to remove them. If you want to apply the first or second option, you will have to do it.
DELETE FROM Permission
WHERE permissionID NOT IN
(SELECT MIN(permissionID) FROM Permission GROUP BY user,location );
Annex 2: Adding a unique contraint to table
If you habe created the schema for the table without the UNIQUE constraint, here is a recipe how to add it.
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;