如何将此Access内部联接查询转换为SQL Server?

时间:2014-03-25 15:18:07

标签: sql sql-server sql-update

我想编写一个更新语句,通过加入MASTER_ID将新代码表与旧代码进行比较。然后,如果NEW_CODE.CODE = 1234 AND OLD_CODE.CODE_ID不在CODE_MAPPING表中,则SET NEW_CODE.CODE_ID = OLD_CODE.CODE_ID AND NEW_CODE.SEQ_NO = OLD_CODE.SEQ_NO。这是我到目前为止,但如果我在CODE_ID列中得到一个空值,它似乎没有正确更新。我想我需要做一个自我加入,但我做的任何事情似乎都没有任何帮助,我将不胜感激。

我有三张包含以下数据的表格:

**NEW_CODE**

    MASTER_ID     SEQ_NO     CODE_ID     CODE
    100            0          XX         1234
    200            0                     5555
    300            0          XX         1234
    300            0          XX         1234

**OLD_CODE**

   MASTER_ID   SEQ_NO   CODE_ID
   100          1        D1           
   200          1        A1
   300          1        
   300          2        Z1

**CODE_MAPPING**

   CODE_ID
   A1
   B1
   C1
   D1

更新声明:

UPDATE NEW
  SET SEQ_NO = OLD.SEQ_NO,
  CODE_ID = OLD.CODE_ID

  FROM NEW_CODE       NEW
  INNER JOIN OLD_CODE      OLD
  ON NEW.MASTER_ID = OLD.MASTER_ID

 LEFT JOIN CODE_MAPPING       CM
  ON OLD.CODE_ID = CM.CODE_ID
  WHERE NEW.CODE = 1234 
  AND CM.CODE_ID IS NULL

更新的表应如下所示:

 **UPDATED NEW_CODE**

        MASTER_ID     SEQ_NO     CODE_ID     CODE
        100            0          XX         1234
        200            0                     5555
        300            1                     1234
        300            2          Z1         1234

所以唯一应该更新的是MASTER_ID为300的两行。但由于某种原因,我得到了以下结果:

 **CURRENT RESULT NEW_CODE**

        MASTER_ID     SEQ_NO     CODE_ID     CODE
        100            0          XX         1234
        200            0                     5555
        300            2          Z1         1234
        300            2          Z1         1234

2 个答案:

答案 0 :(得分:1)

由于您有两个具有相同标识符(MASTER_ID)的行,因此需要使用tsql而不是简单语句。

要更新的行的前提条件: NEW中的每一行都可以与OLD中的一行匹配并反向。 我们需要一个标准来识别NEW中的更新行。我在这里使用SEQ_NO = 0.

  1. 需要OLD和NEW中每一行的唯一键。您的示例数据不包含唯一键。所以我将一个添加到OLD,一个添加到NEW。它最终可以放弃。

    alter table OLD add IDX int IDENTITY(1,1) alter table NEW add IDX int IDENTITY(1,1)

  2. 在OLD上声明游标(只有要更新的行)

    DECLARE @IdxOld int DECLARE @IdxNew int

    宣告MY_CURSOR CURSOR   本地静态READ_ONLY FORWARD_ONLY 对于 SELECT idx 来自老人 什么不存在(SELECT * FROM CODE_MAPPING CM                 WHERE OLD.CODE_ID = CM.CODE_ID)

  3. 在OLD上做foreach并更新NEW

    打开MY_CURSOR FETCH NEXT从MY_CURSOR INTO @IdxId WHILE @@ FETCH_STATUS = 0 开始

    SELECT @IdxNew = Min(Idx) -- min to get only one row
      FROM NEW
      INNER JOIN OLD_CODE OLD  ON NEW.MASTER_ID = OLD.MASTER_ID
    WHERE NEW.CODE = 1234 
        AND OLD.IDX = @IdxOld -- current row from old
        AND SEQ_NO=0 -- row not updated yet         
    
    UPDATE NEW
      SET SEQ_NO = OLD.SEQ_NO,
      CODE_ID = OLD.CODE_ID
    FROM NEW_CODE NEW
      INNER JOIN OLD_CODE  OLD  ON NEW.MASTER_ID = OLD.MASTER_ID
    WHERE NEW.IDX = @IdxNew
      AND OLD.IDX = @IdxOld
    
    FETCH NEXT FROM MY_CURSOR INTO @IdxId
    

    END 关闭MY_CURSOR DEALLOCATE MY_CURSOR

  4. 删除IDX列

    alter table OLD drop COLUMN IDX

    alter table NEW drop COLUMN IDX

答案 1 :(得分:0)

更新中的别名不匹配。 。 。 new不是new_code。试试这个:

UPDATE NC
  SET SEQ_NO = OC.SEQ_NO,
      CODE_ID = OC.CODE_ID
  FROM NEW_CODE NC INNER JOIN
       OLD_CODE OC
       ON NC.MASTER_ID = OC.MASTER_ID LEFT JOIN
       CODE_MAPPING CM
       ON OC.CODE_ID = CM.CODE_ID
  WHERE NC.CODE = 1234 AND CM.CODE_ID IS NULL;