Question

I have a scenario whereby I have a table of data I wish to import into my schema. The key field on the import t\ble AND my target table is a field called MEMBERNO

Before importing, I check if any of the rows in the import table have a MEMBERNO that currently exists within the target table. If so, I wish to amend the MEMBERNO on the import table to the next available value before starting the import (a simple INSERT INTO targetTable SELECT * FROM importTable)

The next available MEMBERNO is currently identified by adding 1 to SELECT MAX(MEMBERNO) FROM targetTable - can I apply this function to several rows in one SQL statement or will I have to create a cursor to loop through? Ideally, I would like to have one UPDATE statement where the value to set is "moving" but I'm not sure this is possible

So something like...

UPDATE importTable SET MEMBERNO = nextavailablenumber 
   WHERE MEMBERNO IN (SELECT MEMBERNO FROM targetTable)

where nextAvailableNumber is computed for each UPDATE

Was it helpful?

Solution

You don't even need to do the update, you can do the check and alter the MemberNo all within the insert to the Target table

INSERT TargetTable (MemberNo, Column1, Column2, Column3)
SELECT  MemberNo = CASE WHEN t.MemberNoExists IS NULL THEN i.MemberNo
                        ELSE n.NextMemberNo + ROW_NUMBER() OVER(PARTITION BY t.MemberNoExists ORDER BY i.MemberNo)
                    END,
        i.Column1,
        i.Column2,
        i.Column3
FROM    ImportTable i
        OUTER APPLY
        (   SELECT  TOP 1 MemberNoExists = 1
            FROM    TargetTable t
            WHERE   t.MemberNo = i.MemberNo
        ) t
        CROSS JOIN 
        (   SELECT  NextMemberNo = MAX(MemberNo) 
            FROM    TargetTable
        ) n;

The subquery t simply generates 1 when the MemberNo already exists, and NULL when it doesn't. If it doesn't exist then the MemberNo from the import table is used.

The subquery n gets the maximum MemberNo in the target table. This is only used where the MemberNo from the import table already exists. Then, so that you don't need a loop it uses ROW_NUMBER to increment this maximum MemberNo by one for each new row to avoid duplicates.

Example on SQL Fiddle (Only with SELECT for demonstration purposes)

If you do still need to do the update you can use a similar query:

WITH Import AS
(   SELECT  NewMemberNo = n.NextMemberNo + ROW_NUMBER() OVER(ORDER BY i.MemberNo),
            i.MemberNo
    FROM    ImportTable i
            CROSS JOIN 
            (   SELECT  NextMemberNo = MAX(MemberNo) 
                FROM    TargetTable
            ) n
    WHERE   EXISTS
            (   SELECT  1
                FROM    TargetTable t
                WHERE   t.MemberNo = i.MemberNo
            ) 
)
UPDATE  Import
SET     MemberNo = NewMemberNo;

UPDATE example on SQL Fiddle

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top