我可以在单个语句中更新两个字段吗?

时间:2016-06-03 04:57:52

标签: sql sql-server

我正在尝试使用case语句更新标志和备注字段:

update [TEMP] 
set FLAG = 
(
case when len(Country) > 3 or len(country) < 3 --or len(country) = 0
then 0 else 1
case when 
)

我还想用第一个案例陈述的“无效国家”更新字段备注,然后为下一个案例陈述更新“无效日期”。

3 个答案:

答案 0 :(得分:2)

要设置两列,您需要一个表单声明:

  UPDATE [TEMP]
     SET col1 = expr1 
       , col2 = expr2

expr1expr2是表达式,用于计算要分配给每列的值。这些可以是简单的文字,也可以是更复杂的表达,例如CASE表达式。

作为一个例子的概述:

  UPDATE [TEMP]
     SET flag   = CASE WHEN ... THEN ... ELSE ... END
       , remark = CASE WHEN ... THEN ... ELSE ... END

表达式可能更复杂。例如,您可以嵌套另一个CASE表达式,连接等。表达式只需返回一个值。在什么条件下,您不清楚要为列分配哪些值。

关注

问:很简单,对于每一行,如果country列中的记录长度超过3个字符,则将该标志设置为0并设置REMARK ='Invalid Country'。同样,如果ISDATE(date_column)= 0,则将flag设置为0并设置REMARK ='In Country Country'

A:做一些简单的事......

  UPDATE [TEMP]
     SET flag   
         = CASE
           WHEN LEN(country) <> 3
           THEN 0
           WHEN ISDATE(date_column) = 0 
           THEN 0 
           ELSE 1
           END
       , remark
         = CASE
           WHEN LEN(country) <> 3
           THEN 'Invalid Country'
           WHEN ISDATE(date_column) = 0 
           THEN 'Invalid Date'      -- ?spec says set to 'Invalid Country'? 
           ELSE ''
           END

答案 1 :(得分:1)

通常,无法在一个SET column_name = sql_expression语句中更新两个字段。 您需要为每列创建update [TEMP] set FLAG = ( case when len(Country) != 3 --or len(country) = 0 then 0 else 1 end ), date = (case when date < getDate() then getDate() else null end ), remark = ( case when len(Country) != 3 then 'Invalid Country' when date < getDate() then 'Invalid date' else null end)

在您的样本中:

SET (column_name, column_name, ...) = (subquery4) 

然而,其他一些DBMS(如Oracle)提供:

SET (column_name1, column_name2)  = 
    (Select CASE WHEN ... THEN .. ELSE ... END,
            CASE WHEN ... THEN .. ELSE ... END .. 

那里有可能:

[2016-06-03 00:13:32,376] [Thread-125] [ath.SeAhRqTyp] INFO- [338aacca-69ca-43ca-9ad1-c623f16ba56f]-outgoing Request is as follows: -
[2016-06-03 00:13:32,376] [Thread-125] [ath.SeAhRqTyp] INFO- [338aacca-69ca-43ca-9ad1-c623f16ba56f]-<soapenv:Envelope 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><out:ARequest </out:ARequest></soapenv:Body></soapenv:Envelope>
[2016-06-03 00:13:33,548] [Thread-125] [ath.EvResp] INFO- [338aacca-69ca-43ca-9ad1-c623f16ba56f]-Ath response is as follow :
[2016-06-03 00:13:33,548] S
[2016-06-03 00:13:33,548] A
[2016-06-03 00:13:33,548] M
[2016-06-03 00:13:33,548] P
[2016-06-03 00:13:33,548] L
[2016-06-03 00:13:33,548] E
[2016-06-03 00:13:33,548] T
[2016-06-03 00:13:33,548] E
[2016-06-03 00:13:33,548] S
[2016-06-03 00:13:33,548] T
[2016-06-03 00:13:33,548] [Thread-125] [ath.EvResp] INFO- [338aacca-69ca-43ca-9ad1-c623f16ba56f]-End of ath response

另一个故事是触发器(当你修改一个字段时,它们允许你修改其他字段 - 但它可能已经离你的问题太远了。)

答案 2 :(得分:1)

如果您想保留判断值是否仅在一个地方有效的逻辑,要删除重复的代码,那么您可以分离决定有效性设置的逻辑值

你可以使用这样的CTE来做到这一点:

CREATE TABLE #peter(id INT PRIMARY KEY, Flag BIT, 
                    Country VARCHAR(30), date DATE, remark VARCHAR(100));

INSERT #peter
    ( id, Flag, Country, date, remark )
VALUES  
    ( 1, 0, 'SWE', '2015-06-01', NULL ),
    ( 2, 0, 'NK', '2016-06-10', NULL );

WITH peter AS (
        SELECT id ,
               Flag ,
               Country ,
               date ,
               remark,
               CASE WHEN date < GETDATE() THEN 0 ELSE 1 END AS isValidDate,
               CASE WHEN LEN(Country) != 3 THEN 0 ELSE 1 END AS isValidCountry
        FROM #peter
        )
UPDATE p
    SET   p.Flag = isValidCountry
        , p.date = CASE WHEN isValidDate = 1 THEN NULL ELSE GETDATE() END 
        , p.remark = CASE 
                        WHEN isValidCountry = 0 AND isValidDate = 0 THEN 'Date and Country is invalid'
                        WHEN isValidDate = 0 THEN 'Date is invalid'
                        WHEN isValidCountry = 0 THEN 'Country is invalid'
                    END  
FROM peter p

...或者通过执行CROSS APPLY中的逻辑:

CREATE TABLE #peter(id INT PRIMARY KEY, Flag BIT, 
                    Country VARCHAR(30), date DATE, remark VARCHAR(100));

INSERT #peter
        ( id, Flag, Country, date, remark )
VALUES  ( 1, 0, 'SWE', '2015-06-01', NULL ),
        ( 2, 0, 'NK', '2016-06-10', NULL );


UPDATE p
   SET    p.Flag = cntry.isValidCountry
        , p.date = CASE WHEN dt.isValidDate = 1 THEN NULL ELSE GETDATE() END 
        , p.remark = CASE 
                        WHEN cntry.isValidCountry = 0 AND dt.isValidDate = 0 THEN 'Date and Country is invalid'
                        WHEN dt.isValidDate = 0 THEN 'Date is invalid'
                        WHEN cntry.isValidCountry = 0 THEN 'Country is invalid'
                    END 

FROM #peter p
CROSS APPLY (SELECT CASE WHEN date < GETDATE() THEN 0 ELSE 1 END) dt(isValidDate)
CROSS APPLY (SELECT CASE WHEN LEN(Country) != 3 THEN 0 ELSE 1 END) cntry(isValidCountry)