Update a 'field' where the 'field' is...

  • Hi everyone,

    I'm trying to do a minor update in a table but have run into a small problem... Basically I have a table of 'Clients', and when a client leaves a termination date is entered and a 'ZZ' is appended to the start of the ClientName field. Quite a few clients have a termination date but their name is yet to have 'ZZ' appended to their name, so I was looking at doing the following:

    Update Clients

    Set ClientName = 'ZZ ' + convert(nvarchar(max),ClientName)

    Where ClientTerminationDate Is Not NULL And ClientName Not Like 'ZZ%'

    That all seemed good but I get the following error:

    Cannot insert duplicate key row in object 'Clients' with unique index 'ClientName'.

    I can sort of understand what it's saying; you can't change a field where that same field is being used to identify the field to be changed. But how else would I do this? I only want to 'ZZ' those names that have a termination date and haven't already been ZZ'ed. I guess I'd need to identuify these clients then store a reference to them to do the actual change?

    Any ideas would be a great help! Thanks.

  • Something like this should get you there:

    Update c1

    Set ClientName = 'ZZ ' + convert(nvarchar(max),ClientName)

    FROM Clients c1

    LEFT JOIN Clients c2 ON 'ZZ ' + convert(nvarchar(max),c1.ClientName) = c2.ClientName

    Where ClientTerminationDate Is Not NULL And ClientName Not Like 'ZZ%' AND c2.ClientName IS NULL

    This assumes that ClientName is the sole primary key. If there are more fields in the primary key, those should be included after ON.


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • Post deleted because I mistakenly quoted above instead of editing it. 😀


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • I'm thinking that the problem is that some clients have already been marked with "ZZ" as a prefix and that if you were to add prefixes to all the clients, you'd find duplicates. Try copying all of the client names to a test table with no constraints, update them all to have a "ZZ" prefix, and then do a dupe check. I believe you'll see what I mean.

    This is also why keys should always be immutable.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Yes thats correct some of the clients have been terminated correctly with the 'ZZ ' appended, so I want to azoid 'ZZ ZZ 'ing them.

    And the 'ClientName' field isn't the primary key, there's a sole 'ClientID' field in the 'Clients' table as well, does that make a difference to being able to solve it in one step? I was thinking I'd need to copy them into a table to do the update like you mention.

    Thanks for the help!

  • Jacobs_r86 (6/19/2012)


    Yes thats correct some of the clients have been terminated correctly with the 'ZZ ' appended, so I want to azoid 'ZZ ZZ 'ing them.

    And the 'ClientName' field isn't the primary key, there's a sole 'ClientID' field in the 'Clients' table as well, does that make a difference to being able to solve it in one step? I was thinking I'd need to copy them into a table to do the update like you mention.

    Thanks for the help!

    You should still be able to do the LEFT JOIN as I suggested.


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • Thanks dwain, that looked to work... somewhat. I just ran some checks and it missed one, or rather it seemed to 'ZZ' its entry in the c2 referenced table and not the c1? I've seen that reference approach used before but not entirely up to speed on it. c1 and c2 are just pointing at the same 'Clients' table aren't they? So how can c1 ClientName not have the 'ZZ' but the c2 ClientName does?

  • Jacobs_r86 (6/19/2012)


    Thanks dwain, that looked to work... somewhat. I just ran some checks and it missed one, or rather it seemed to 'ZZ' its entry in the c2 referenced table and not the c1? I've seen that reference approach used before but not entirely up to speed on it. c1 and c2 are just pointing at the same 'Clients' table aren't they? So how can c1 ClientName not have the 'ZZ' but the c2 ClientName does?

    What you are calling a reference is actually referred to as the table alias. Let's look at the code again:

    Update c1

    Set ClientName = 'ZZ ' + convert(nvarchar(max),ClientName)

    FROM Clients c1

    LEFT JOIN Clients c2 ON 'ZZ ' + convert(nvarchar(max),c1.ClientName) = c2.ClientName

    Where ClientTerminationDate Is Not NULL And ClientName Not Like 'ZZ%' AND

    c2.ClientName IS NULL

    I added two parts to it. The LEFT JOIN and "AND c2.ClientName is NULL"

    1. LEFT JOIN joins the table onto itself as you have deduced (c1 and c2 refer to the same table). The c2 table should already have ZZ applied to its ClientNames. So doing the LEFT JOIN as I have should result in c2.ClientName being non-NULL in cases where that ZZ-ClientName already exists.

    2. The addition to the WHERE just makes sure that you only allow the UPDATE where the ClientName (with the ZZ) does not exist.

    I'm not sure why it might have missed one without having more information.


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • I see what you mean and it makes sense but there were 39 records that got updated out of the possible 40. It looks to be failing on 'c2.ClientName IS NULL', as that field has the ZZ'ed SortName in it. But if I were to take that clause out, then i'll have the problem you mention in point 2.

    One thing, I get 'ambiguous' errors with your code but I understand you mean the following:

    UPDATE c1

    SET ClientName = 'ZZ ' + convert(nvarchar(max),ClientName)

    FROM Clients c1

    LEFT JOIN Clients c2 ON 'ZZ ' + convert(nvarchar(max),c1.ClientName) = c2.ClientName

    WHERE c1.ClientTerminationDate IS NOT NULL AND c1.ClientName NOT LIKE 'ZZ%' AND

    c2.ClientName IS NULL

    Also, Just out of interest I removed the ZZ on one of the clients that had it automatically applied and when i run a lookup (minus the "WHERE c2.ClientName IS NULL") I get both records with the one I just manually removed the ZZ from having NULL in c2.ClientName field and the one that didn't update having its ZZed ClientName in there. So I'm not sure whats going on...

  • Jacobs_r86 (6/20/2012)


    I see what you mean and it makes sense but there were 39 records that got updated out of the possible 40. It looks to be failing on 'c2.ClientName IS NULL', as that field has the ZZ'ed SortName in it. But if I were to take that clause out, then i'll have the problem you mention in point 2.

    One thing, I get 'ambiguous' errors with your code but I understand you mean the following:

    UPDATE c1

    SET ClientName = 'ZZ ' + convert(nvarchar(max),ClientName)

    FROM Clients c1

    LEFT JOIN Clients c2 ON 'ZZ ' + convert(nvarchar(max),c1.ClientName) = c2.ClientName

    WHERE c1.ClientTerminationDate IS NOT NULL AND c1.ClientName NOT LIKE 'ZZ%' AND

    c2.ClientName IS NULL

    Also, Just out of interest I removed the ZZ on one of the clients that had it automatically applied and when i run a lookup (minus the "WHERE c2.ClientName IS NULL") I get both records with the one I just manually removed the ZZ from having NULL in c2.ClientName field and the one that didn't update having its ZZed ClientName in there. So I'm not sure whats going on...

    You might want to try this to help diagnose your problem.

    SELECT c1.*, c2.*

    FROM Clients c1

    LEFT JOIN Clients c2 ON 'ZZ ' + convert(nvarchar(max),c1.ClientName) = c2.ClientName

    WHERE c1.ClientTerminationDate IS NOT NULL AND c1.ClientName NOT LIKE 'ZZ%' AND

    c2.ClientName IS NULL

    The ambiguous error was probably on this:

    convert(nvarchar(max),ClientName)

    Which should have been this:

    convert(nvarchar(max),c1.ClientName)


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • Thanks dwain, found the problem (which I would have found a lot quicker if I took note of your first reply in relation to primary keys). There were 2 records with the same ClientName, or rather a client left and was ZZed then returned and rather then reactivating their old terminated account (removing the ZZ) someone created a new account in the same name. Then it looks like the client has left again hence another termination date was entered on the newer account but attempts to have the ClientName ZZed again throw an error because that name already exists.

    The defining factor here though is that they had different ClientIDs. Thanks for all your help with this, I've learnt a lot!

  • Jacobs_r86 (6/20/2012)


    Thanks dwain, found the problem (which I would have found a lot quicker if I took note of your first reply in relation to primary keys). There were 2 records with the same ClientName, or rather a client left and was ZZed then returned and rather then reactivating their old terminated account (removing the ZZ) someone created a new account in the same name. Then it looks like the client has left again hence another termination date was entered on the newer account but attempts to have the ClientName ZZed again throw an error because that name already exists.

    The defining factor here though is that they had different ClientIDs. Thanks for all your help with this, I've learnt a lot!

    Glad to hear I have another satisfied client!

    No need to terminate your account at this time. 😛 ZZzzz...


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • 😀 This forum has proven a handy resource so I'll be sticking around, especially now I have a post count above 1 😎

  • Should have C2 Table ZZ used in its ClientNames.

    Try harder and harder to know Platform thick heels shoes everywhere!

Viewing 14 posts - 1 through 13 (of 13 total)

You must be logged in to reply to this topic. Login to reply