使用一个SQL语句更新表中的多行,每行具有计算值

时间:2013-12-31 13:58:24

标签: sql sql-server-2008 rdbms

我有一个场景,我希望将一个数据表导入到我的架构中。导入和目标表上的关键字段是名为MEMBERNO

的字段

在导入之前,我检查导入表中的任何行是否具有目标表中当前存在的MEMBERNO。如果是这样,我希望在开始导入之前将导入表上的MEMBERNO修改为下一个可用值(一个简单的INSERT INTO targetTable SELECT * FROM importTable

当前通过向SELECT MAX(MEMBERNO) FROM targetTable添加1来识别下一个可用的MEMBERNO - 我可以将此函数应用于一个SQL语句中的多个行,还是必须创建一个循环的游标?理想情况下,我想有一个UPDATE语句,其中设置的值是“移动”但我不确定这是否可能

就像......

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

其中为每个UPDATE

计算nextAvailableNumber

1 个答案:

答案 0 :(得分:2)

您甚至不需要进行更新,您可以检查并更改插入目标表中的MemberNo全部

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;

当MemberNo已经存在时,子查询t只生成1,而当它不存在时,则生成NULL。如果它不存在,则使用导入表中的MemberNo。

子查询n获取目标表中的最大MemberNo。仅在导入表中的MemberNo已存在的情况下使用。然后,为了不需要循环,它使用ROW_NUMBER将每个新行的最大MemberNo增加1,以避免重复。

Example on SQL Fiddle (仅限SELECT用于演示目的)

如果您仍然需要进行更新,可以使用类似的查询:

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