TSQL,如何只更新第一个可用桶,

时间:2018-04-10 17:22:35

标签: sql-server tsql

我需要进行此更新,以便为一系列存储桶添加另一个值(B1-B5),但只有一次进入第一个存储区,如下面的示例所示,一旦填充就无法提供任何解决方案来标记它,试图使用旗帜,但看起来它并没有'在相同的tx期间工作。这是示例代码,但尚未正确。我是MSQL 2016。 谢谢大家的评论;

/*
SELECT * INTO #t FROM (
SELECT 101 CustID, 100 B1, 200 B2 , NULL B3, NULL B4, NULL B5, '0' [f], 111 NewB , 'B4,B5 sbe empty' Note UNION
SELECT 102 CustID, 100 B1, 200 B2 , 300 B3, NULL B4,  NULL B5, '0' [f], 222 NewB , '22 goes only into B4, B5 empty' Note   UNION
SELECT 103 CustID, 100 B1, 200 B2 , 300 B3, 400  B4 , NULL B5, '0' [f], 333 NewB , '333 goes into B5' Note    )x                       */
--     SELECT * FROM #t              -- before                  DROP TABLE #t


-- how to Put  NewB only ONCE into first empty B1-5
update #t 
SET B1 = CASE WHEN B1 IS NULL THEN NewB ELSE B1 END,   
    B2 = CASE WHEN B2 IS NULL THEN NewB ELSE B2 END,
    B3 = CASE WHEN B3 IS NULL THEN NewB ELSE B3 END,
    B4 = CASE WHEN B4 IS NULL THEN NewB ELSE B4 END,
    B5 = CASE WHEN B5 IS NULL THEN NewB ELSE B5 END 

    SELECT * FROM #t
----------------------

CustID  B1   B2  B3  B4  B5 _   NewB    Note
101    100  200 111 111 111 -   111     B4,B5 sbe empty
102    100  200 300 222 222 -   222     B5 sbe empty
103    100  200 300 400 333 -   333     333 goes into B5

**  tried :   f = CASE WHEN B1 IS NULL  THEN 1 ELSE 0 END   ,
A column cannot be assigned more than one value in the same clause

4 个答案:

答案 0 :(得分:1)

测试所有先前的值是否为空,即尚未设置。

update #t
SET B1 = CASE WHEN B1 IS NULL THEN NewB ELSE B1 END,   
    B2 = CASE WHEN B2 IS NULL AND
        B1 IS NOT NULL THEN NewB ELSE B2 END,
    B3 = CASE WHEN B3 IS NULL AND
        B1 IS NOT NULL AND B2 IS NOT NULL THEN NewB ELSE B3 END,
    B4 = CASE WHEN B4 IS NULL AND
        B1 IS NOT NULL AND B2 IS NOT NULL AND B3 IS NOT NULL THEN NewB ELSE B4 END,
    B5 = CASE WHEN B5 IS NULL AND 
           B1 IS NOT NULL AND B2 IS NOT NULL AND B3 IS NOT NULL AND B4 IS NOT NULL
         THEN NewB ELSE B5 END
    SELECT * FROM #t

另请参阅:Importance of Column Order in the SET Clause in Update Statements

答案 1 :(得分:1)

您应该检查前面所有列的值:

update #t 
SET B1 = CASE WHEN B1 IS NULL THEN NewB ELSE B1 END,   
    B2 = CASE WHEN B1 IS NULL AND B2 IS NULL THEN NewB ELSE B2 END,
    B3 = CASE WHEN B1 IS NULL AND B2 IS NULL AND B3 IS NULL THEN NewB ELSE B3 END,
    B4 = CASE WHEN B1 IS NULL AND B2 IS NULL AND B3 IS NULL AND B4 IS NULL THEN NewB ELSE B4 END,
    B5 = CASE WHEN B1 IS NULL AND B2 IS NULL AND B3 IS NULL AND B4 IS NULL AND B5 IS NULL THEN NewB ELSE B5 END 

或者,您可以使用单独的更新语句,但在影响该行的第一个UPDATE中删除NewB的值:

ALTER TABLE #t ALTER COLUMN NewB INT NULL

update #t SET B1 = NewB, NewB=NULL WHERE B1 IS NULL AND NewB IS NOT NULL
update #t SET B2 = NewB, NewB=NULL WHERE B2 IS NULL AND NewB IS NOT NULL
update #t SET B3 = NewB, NewB=NULL WHERE B3 IS NULL AND NewB IS NOT NULL
update #t SET B4 = NewB, NewB=NULL WHERE B4 IS NULL AND NewB IS NOT NULL
update #t SET B5 = NewB, NewB=NULL WHERE B5 IS NULL AND NewB IS NOT NULL

答案 2 :(得分:1)

您可以使用CROSS APPLY创建一个引用字段,指示应更新哪个列。在下面的代码中,如果需要,IIF可以替换为CASE表达式。

UPDATE t
SET B1 = IIF(NextBucket = 'B1', NewB, B1)
  , B2 = IIF(NextBucket = 'B2', NewB, B2)
  , B3 = IIF(NextBucket = 'B3', NewB, B3)
  , B4 = IIF(NextBucket = 'B4', NewB, B4)
  , B5 = IIF(NextBucket = 'B5', NewB, B5)
FROM #t t
     CROSS APPLY (SELECT NextBucket = CASE
                                          WHEN B1 IS NULL THEN 'B1'
                                          WHEN B2 IS NULL THEN 'B2'
                                          WHEN B3 IS NULL THEN 'B3'
                                          WHEN B4 IS NULL THEN 'B4'
                                          WHEN B5 IS NULL THEN 'B5'
                                        END) nb;

答案 3 :(得分:1)

update #t
SET 
b1 = coalesce( b1, newb),
b2 = case when b1 is not null then coalesce(b2, newb) else b2 end,
b3 = case when b1 is not null and b2 is not null then  coalesce(b3, newb)  else b3 end,
b4 = case when b1 is not null and b2 is not null and b3 is not null then coalesce(b4, newb) else b4 end,
b5 = case when b1 is not null and b2 is not null and b3 is not null and b4 is not null then coalesce(b5, newb) else b5 end