简体   繁体   中英

Why did this UPDATE change all rows instead of just one row?

I have made some SQL code to (what I thought) would update 1 field for only some records. The code I made was:

UPDATE Name
SET name.STATUS = 'a'
WHERE EXISTS
    (SELECT Name.ID,
            Name.MEMBER_TYPE,
            Name.CATEGORY,
            Name.STATUS,
            Name.COMPANY_SORT,
            Name.FULL_NAME,
            Name.TITLE,
            Name.FUNCTIONAL_TITLE,
            Activity.ACTIVITY_TYPE,
            Activity.PRODUCT_CODE,
            Activity.TRANSACTION_DATE
     FROM Name
     INNER JOIN Activity ON Name.ID = Activity.ID
     WHERE ACTIVITY_TYPE = 'ELECTIONS'
       AND PRODUCT_CODE LIKE '%new%'
       AND TRANSACTION_DATE LIKE '%2014%'
       AND name.MEMBER_TYPE IN ('mcm',
                                'MCNM'))

but it updated all the records in the name name to the status of a , not just the one in the where exist statement ... what have I screwed up?

Try something like this:

UPDATE Name
SET name.STATUS = 'a'
WHERE EXISTS
    (SELECT *
     FROM Activity
     WHERE Name.ID = Activity.ID
       AND ACTIVITY_TYPE = 'ELECTIONS'
       AND PRODUCT_CODE LIKE '%new%'
       AND TRANSACTION_DATE LIKE '%2014%'
       AND name.MEMBER_TYPE IN ('mcm', 'MCNM')
    )

Some explanation: when you do FROM Name in the inner query you mask outer table Name and just query whole thing. So inner query is the same for every entry. You need to reuse Name from outer query so that inner query relates to outer. Sorry, my code might need some polishing I don't even know what DB you are using.

You need to join the outer query "Name" table to the subquery. Note the addition in the where criteria. I haven't run this, but it should point you in the right direction.

    UPDATE Name
SET name.STATUS = 'a'
WHERE EXISTS
    (SELECT innerName.ID,
            innerName.MEMBER_TYPE,
            innerName.CATEGORY,
            innerName.STATUS,
            innerName.COMPANY_SORT,
            innerName.FULL_NAME,
            innerName.TITLE,
            innerName.FUNCTIONAL_TITLE,
            Activity.ACTIVITY_TYPE,
            Activity.PRODUCT_CODE,
            Activity.TRANSACTION_DATE
     FROM Name innerName
     INNER JOIN Activity ON innerName.ID = Activity.ID
     WHERE ACTIVITY_TYPE = 'ELECTIONS'
AND innerName.ID = Name.ID
       AND PRODUCT_CODE LIKE '%new%'
       AND TRANSACTION_DATE LIKE '%2014%'
       AND innerName.MEMBER_TYPE IN ('mcm',
                                'MCNM'))

There's no link between the data selection of the UPDATE statement, versus what you define in the SUB-SELECT (that starts after the EXISTS clause). Basically, it says to update all, if the below select has any record at all.

The EXISTS clause is not intelligent enough to know what record you are talking about. You have to tell him.

The issue is that your reference to Name in the update line and your reference to Name under the sub-query are treated as two separate instances, so there is no relation between the update statement and the sub-query.

To get around it, you can actually alias your tables within the sub-query itself, and then explicitly refer to the alias in the update:

UPDATE nm
SET nm.STATUS = 'a'
WHERE EXISTS
    (SELECT *
     FROM Name nm
     INNER JOIN Activity act ON nm.ID = act.ID
     WHERE ACTIVITY_TYPE = 'ELECTIONS'
       AND PRODUCT_CODE LIKE '%new%'
       AND TRANSACTION_DATE LIKE '%2014%'
       AND nm.MEMBER_TYPE IN ('mcm',
                              'MCNM'))

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