简体   繁体   中英

MYSQL: How do I perform an INSERT inside a SELECT?

I am attempting to perform an insert operation inside a select. This is for chaining multiple inserts together that are dependent on each other. As such it looks something like this.

INSERT (Parent)
--SELECT (Return the Child's uuid created and assigned by TRIGGER)
---INSERT (Child)

Every record in the database has a uuid assigned upon insert through a trigger. I have a table for each type of entity I am capturing (eg person,address,phone,email).

Solution 1: I can insert a dependent entity such as the phone first, select it's uuid, then include that in the parent entity. In this case "person".

Solution 2: I can create the parent entity, then the dependent, then update the parent after acquiring the dependents uuid.

Solution 3: What I want to do is create the dependents at the same time I am creating the parent, and return their uuid to the parent for the parent record insert. This relies on order of operations to ensure everything is happening in appropriate order.

Because of the issues with mysql array support, I'm fudging a parent/child uuid_array table. As such there are additional operations involved, but the given example is a lot simpler.

Any idea on how to pull this off? Is there a better way to return the uuid?

INSERT INTO person (Name_First,Name_Middle,Name_Last,Phone_UUID_Array)
VALUES  (
    'John',
    'Diddly',
    'Doe',
    SELECT @last_uuid
        INSERT INTO phone (Phone_Number,Phone_Type)
        VALUES  (
            '1-555-555-5555',
            (SELECT UUID FROM VIEW_TYPE_CATEGORY WHERE Reference_Type='Personal cell' AND Category='phone')
        )
);

Examples of triggers I've created for every table

CREATE TRIGGER uuid_person BEFORE INSERT ON person FOR EACH ROW SET NEW.UUID = UUID();
CREATE TRIGGER last_uuid_person AFTER INSERT ON person FOR EACH ROW SET @last_uuid = NEW.UUID;

CREATE TRIGGER uuid_phone BEFORE INSERT ON phone FOR EACH ROW SET NEW.UUID = UUID();
CREATE TRIGGER last_uuid_phone AFTER INSERT ON phone FOR EACH ROW SET @last_uuid = NEW.UUID;

No, you cannot execute an INSERT "inside" a SELECT, nor can you execute an INSERT inside another INSERT.

You can play around with triggers, but IMHO that's more trouble than it's worth.

I would recommend not doing this with a trigger, but instead generate the uuid and save it in a session variable. Then you can use it in as many subsequent statements as you want.

SELECT UUID() INTO @phone_uuid;

INSERT INTO phone (Uuid,Phone_Number,Phone_Type) VALUES (@phone_uuid, ...);

INSERT INTO person (Name_First,Name_Middle,Name_Last,Phone_UUID_Array)
VALUES ('John', 'Diddly', 'Doe', @phone_uuid);

These session variables are scoped to the session, so you don't have to worry about concurrent clients doing their own work overwriting yours, even if each session is using the same variable names.

Also, I fear from your description that Phone_UUID_Array is a comma-separated list of UUID's. You are probably not going to be happy with that design, for a number of other reasons .

You've got the reference in the wrong direction. Person shouldn't try to have a reference to all its dependent phone numbers. Go the other way -- each row in phone should have a reference to its parent person . That way you don't need to have a comma-separated list, and you can insert them in a more sensible order -- parent first, then one or more phone rows that each references the same parent. You don't need to update parent after inserting the phone .

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