Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL composite primary key without ordering (pair of integers in either order must be unique)

I have a MySQL table for Users with the primary key _id, and I want to represent friendships (visibility on friends lists of other users) as a table with pairs of userId foreign keys. I'm thinking something like:

CREATE TABLE UserFriendships (
  userIdA INT NOT NULL,
  userIdB INT NOT NULL,
  PRIMARY KEY (userIdA, userIdB),
  FOREIGN KEY (userIdA) REFERENCES Users(_id)
  FOREIGN KEY (userIdB) REFERENCES Users(_id)
)

It's my understanding that this will allow both (userIdA = 2, userIdB = 7) and (userIdA = 7, userIdB = 2) to be inserted as distinct rows. I want one row per friendship, that is to say one row per pair of userIds.

Does anyone know how I could improve this? Even if the above constraint is met, to get a list of all the friends of user foo I have to do a union, something like: SELECT userIdB AS friendUserId WHERE userIdA = foo UNION SELECT userIdA WHERE userIdB = foo. Is this the best way to accomplish that query, or should I think about changing my schema?

like image 611
Mike Turley Avatar asked Mar 31 '13 18:03

Mike Turley


People also ask

Do composite primary keys have to be unique?

A Composite Primary Key is created by combining two or more columns in a table that can be used to uniquely identify each row in the table when the columns are combined, but it does not guarantee uniqueness when taken individually, or it can also be understood as a primary key created by combining two or more ...

Does order matter in composite primary key?

The order of primary key columns isn't a performance consideration for queries that specify all columns of the composite primary key. However, column order is very important for queries that specify only a subset of the columns. For example, the primary key (clustered) of the Sales.

Does primary key need to be unique?

Primary keys must contain UNIQUE values, and cannot contain NULL values. A table can have only ONE primary key; and in the table, this primary key can consist of single or multiple columns (fields).

Is primary key always unique in SQL?

Primary key is always unique in every SQL. You dont have to explicitly define it as UNIQUE. On a side note: You can only have onePrimary key in a table and it never allows null values.


1 Answers

You can use a TRIGGER BEFORE INSERT to enfore a business rule:

  • userIdA is always the user with the lower ID and userIdB always the user with the higher ID

This way both combinations (A,B) and (B,A) result in the same column order with the same primary key.

DELIMITER |
CREATE TRIGGER enforce_friendship_id_order BEFORE INSERT ON UserFriendships
  FOR EACH ROW BEGIN
    SET @lowerId := IF(NEW.userIdA < NEW.userIdB, NEW.userIdA, NEW.userIdB);
    SET @higherId := IF(NEW.userIdA > NEW.userIdB, NEW.userIdA, NEW.userIdB);
    SET NEW.userIdA = @lowerId;
    SET NEW.userIdB = @higherId;
  END;
|
DELIMITER ;
like image 145
Kaii Avatar answered Oct 14 '22 15:10

Kaii