Insert but only if a condition on another table is met

Viewed 47

I have 3 tables for a messaging system

Conversations

| id |

Participants

| id | conversation | user |

Messages

| id | conversation | user | text |

I want to restrict messages being inserted into a conversation if the user is not part of through the participants table

I think I could structure it in a better way by having participant in the messages table. But then id have to do an extra query by seeing what a users participant id is before inserting a message.

Id rather do it with a constraint or foreign key. What would the best way to do this be?

2 Answers

You can use EXISTS in the INSERT statement:

INSERT INTO Messages(id, conversation, user, text)
SELECT :id, :conversation, :user, :text
FROM dual
WHERE EXISTS (
  SELECT 1 
  FROM Participants 
  WHERE conversation = :conversation AND user = :user
) 

If your version of MySql is 8.0+ you can omit FROM DUAL.

Replace :id, :conversation, :user and :text with the column values that you want to insert.

If ID is an autoincremented integer change to:

INSERT INTO Messages(conversation, user, text)
SELECT :conversation, :user, :text
................................

Or, first create a UNIQUE constraint for the combination of columns conversation and user in Participants:

ALTER TABLE Participants ADD CONSTRAINT unique_conv_user UNIQUE (conversation, user)

and then add a foreign key constraint for the combination of columns conversation and user in Messages:

ALTER TABLE Messages 
ADD CONSTRAINT fk_conv_user 
FOREIGN KEY (conversation, user) REFERENCES Participants(conversation, user);

This way you can only insert new rows in Messages if the combination of conversation and user already exists in Participants.

Is this a trick question? You just described the main use case of referential integrity in a data base. Make Messages.(ID, User) a foreign key of the Participants table.

Related