简体   繁体   中英

SQL--How can I add a constraint based on multiple joined tables in an INSERT statement?

I am attempting to limit the creation of a new record in a cross table to Active records in the respective primary tables. In this example, the Owners table and the Pets table each contain an 'Active' column with a boolean data type. The cross table contains columns for OwnerId and PetId. I do not want the INSERT statement to fire unless both the Owner and the Pet are Active.

The unconstrained statement follows:

INSERT INTO OwnerPets (Id, OwnerId, PetId) 
VALUES (NEWID()
, 1234
, 2345)

I have seen numerous examples online showing how to insert data from a joined table using a SELECT FROM WHERE constraint, but that is not what I am trying to do here.

I am able to accomplish this constraint in my UPDATE statement, and I include it here in case it provides any additional insight. The updated values are pulled from the UI.

UPDATE OwnerPets
SET
 OwnerID=1234
, PetId=2345
, DateAcquired='2021-01-23'
, CurrentOnVaccinations=1
, LastModifyDate=CURRENT_TIMESTAMP
, Comment='My Comments'
FROM OwnerPets 
INNER JOIN Owners ON OwnerPets.OwnerId = Owners.Id
INNER JOIN Pets ON OwnerPets.PetId = Pets.Id 
WHERE OwnerPets.Id=3456 
AND Owners.Active = 1
AND Pets.Active = 1

I am attempting to do something similar with INSERT but nothing I have tried seems to work. Any help would be appreciated!

You can use select with insert. If query from the two tables in this select -- no rows will be returned if where is not valid. Like this:

INSERT INTO OwnerPets (Id, OwnerId, PetId) 
  SELECT NEWID(), O.Id, P.Id
  FROM Owners O, Pets P
  WHERE O.Id=1234 AND O.Active = 1
  AND P.Id = 2345 AND P.Active = 1

You can create a Trigger to check if both the owner and the pet before executing the insert statement.

Something like:

CREATE TRIGGER check_active_owner_and_pet BEFORE INSERT ON OwnerPets
   FOR EACH ROW
   BEGIN
       DECLARE ownerIsActive INT;
       DECLARE petIsActive INT;

       SELECT o.Active INTO ownerIsActive FROM Owners o WHERE o.Id = NEW.OwnerId;
       SELECT p.Active INTO petIsActive FROM Pets p WHERE p.Id = NEW.PetId;

       IF ownerIsActive <> 1 OR petIsActive <> 1 THEN
           SIGNAL SQLSTATE '45000' 
           SET MESSAGE_TEXT = "your error text";
       END IF;
   END;

The NEW indentifier refers to the record about to be inserted.

The SIGNAL statement is the way you can throw an error in MySQL.

(I recommend you check the documentation for your current MySQL version just in case)

Also, check this other question that refers to a similar problem.

There was some conversation on SIGNAL statement and how to use it in a BEFORE INSERT trigger.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM