简体   繁体   中英

MySQL UPDATE one table with values from another table if they're not equal

I have two tables:

SELECT
    d.id,
    d.permission_lookup_id,
    d.permission_object_id,
    f.id,
    f.permission_lookup_id,
    f.permission_object_id
FROM
    folders f
LEFT JOIN
    documents d
    ON f.id = d.folder_id
WHERE
    d.permission_lookup_id != f.permission_lookup_id OR
    d.permission_object_id != f.permission_object_id

In theory this should return nothing if all is well, but it isn't, I receive hundres of thousands of results (currently 407,343). I need to update the documents table so that permission_lookup_id matches folders 's permission_lookup_id and likewise for permission_object_id , based off of documents.parent_id as the foreign key constraint.

I tried the following query with little success:

UPDATE 
    folders f
LEFT JOIN
    documents d
    ON f.id = d.folder_id
SET
    d.permission_lookup_id = f.permission_lookup_id,
    d.permission_object_id = f.permission_object_id
WHERE
    d.permission_lookup_id != f.permission_lookup_id OR
    d.permission_object_id != f.permission_object_id

After running that it tells me that 70,986 rows affected, and 407343 rows matched, yet I still have results from the first select query.

EDIT: Both of the following queries return 0 rows:

SELECT * FROM folders WHERE permission_lookup_id IS NULL OR permission_object_id IS NULL;

SELECT * FROM documents WHERE permission_lookup_id IS NULL OR permission_object_id IS NULL;

Same goes for blank values as well.

EDIT 2: There was an amateur mistake made in my original select/update queries. In the WHERE clause, I had:

WHERE
    d.permission_lookup_id != f.permission_lookup_id OR
    d.permission_object_id != f.permission_lookup_id

Where I should have had

WHERE
    d.permission_lookup_id != f.permission_lookup_id OR
    d.permission_object_id != f.permission_object_id

That was causing me to receive false positives, and merely would have caused nothing more than to have the updates go through and update every column regardless of whether or not it needed to. Sorry for the confusion.

How about this alternative syntax:

UPDATE 
    folders f, documents d
SET
    d.permission_lookup_id = f.permission_lookup_id,
    d.permission_object_id = f.permission_object_id
WHERE
    f.id = d.folder_id AND (
    d.permission_lookup_id != f.permission_lookup_id OR
    d.permission_object_id != f.permission_lookup_id)

The manual says JOIN clauses are ok, but I'm curious to see if there's any difference.

The preceding example shows an inner join that uses the comma operator, but multiple-table UPDATE statements can use any type of join permitted in SELECT statements, such as LEFT JOIN.

Is is possible that the permission_lookup_id from either table has NULL values? If so, you might want to try using the NULL-safe operator:

WHERE
    (NOT d.permission_lookup_id <=> f.permission_lookup_id) OR
    (NOT d.permission_object_id <=> f.permission_lookup_id)

UPDATE

Try one field at time just to see and use the following syntax (this might take a longer to run):

UPDATE folders f
SET f.permission_lookup_id =COALESCE((SELECT d.permission_lookup_id FROM documents d
                                      WHERE f.id = d.folder_id
                                      AND d.permission_lookup_id != f.permission_lookup_id),
                                      f.permission_lookup_id)

Try using inner join in your query instead of left join and please let me know that whether your id field has null values? If yes, then it needs a different approach

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