使用一个更新语句在列中切换值


12

您发现系统中的错误已在数据库中错误地将男性(M)命名为女性(W),反之亦然。列仅允许一个字符。在不使用任何临时表的情况下,编写一个更新查询来解决此问题。

这个问题是在我最近进行的一次采访中提出的,我打算进行更多可能有类似问题的采访,所以我想对如何处理这个问题有所了解。


6
是否要求您采用特定的数据库产品?例如MySQL,SQL Server,Oracle,PostgreSQL ...?
保罗怀特9

您的系统是否已阅读新的社区准则?:\
AER

Answers:


23

您要使用CASE某种类型的表达式。

在SQL Server中,代码如下所示:

UPDATE TableName
SET gender = CASE WHEN gender = 'M' THEN 'W' 
                  WHEN gender = 'W' THEN 'M'
                  ELSE gender END

编辑: 如注释(和一些其他答案)中所述,如果在语句上放置WHERE子句,则ELSE不是必需的。

UPDATE TableName
SET gender = CASE WHEN gender = 'M' THEN 'W' 
                  WHEN gender = 'W' THEN 'M' END
WHERE gender IN ('M','W')

这样可以避免不必要的更新。无论哪种情况,重要的是要记住,除了M&W(例如NULL)以外,还有其他选项,并且您不想输入错误的信息。例如:

UPDATE TableName
SET gender = CASE WHEN gender = 'M' THEN 'W' 
                  ELSE 'M' END

这会将所有NULL(或其他可能的性别)替换为不正确的'M'。


还有两个其他选择

/*Simple form of CASE rather than Searched form*/
UPDATE TableName
SET    gender = CASE gender
                  WHEN 'M' THEN 'W'
                  WHEN 'W' THEN 'M'
                END
WHERE  gender IN ( 'M', 'W' );

更简洁

/*For SQL Server 2012+*/
UPDATE TableName
SET    gender = IIF(gender = 'M', 'W', 'M')
WHERE  gender IN ( 'M', 'W' ); 

1
您可以替换为IIF()IF()它将在MySQL中工作;)
ypercubeᵀᴹ17年

9

在Oracle中,您可以使用CASE,因为其他答案如下:

UPDATE TableName
SET gender = CASE WHEN gender = 'M' THEN 'W' 
                  WHEN gender = 'W' THEN 'M'
             END
WHERE gender in ('M','W');

您还可以使用DECODE:

UPDATE TableName SET gender = DECODE(gender,'M','W','W','M')
WHERE gender in ('M','W');

5

为了仅在两个值之间切换,您还可以尝试以下技巧,该技巧不使用CASE表达式(此处假设Transact-SQL):

UPDATE
  YourTable
SET
  Gender = CHAR(ASCII('M') + ASCII('W') - ASCII(Gender))
WHERE
  Gender IN ('M', 'W')
;

根据的当前值GenderASCII(Gender)将取消ASCII('M')ASCII('W'),从而使该CHAR()函数要转换的其他代码返回到相应的字符。

不过,我将其留作比较。尽管此选项可能带有高雅的外观,但是使用CASE表达式的解决方案可以说更具可读性,因此更易于维护,并且肯定会更容易扩展为两个以上的值。


2
我们希望所有MW都以大写形式输入,以避免7结果中出现意外或`-`的情况。
马丁·史密斯

@MartinSmith:非常好。如果他们没有,我们就不得不更换ASCII(Gender)ASCII(UPPER(Gender)),这是那么优雅,但并不多。
Andriy M'1

@MartinSmith如果有m和w的小写字母,它们不会被该WHERE子句拒绝吗?
ypercubeᵀᴹ

1
@YperSillyCubeᵀᴹ-仅在区分大小写的排序规则中(不是通常的IME)
Martin Smith

4

您可以使用case ... when表达式来做到这一点:

mysql> select * from genderswap;
+--------+
| gender |
+--------+
| F      |
| F      |
| M      |
| M      |
| M      |
| M      |
| M      |
+--------+
7 rows in set (0.00 sec)

mysql> 
mysql> UPDATE genderswap SET gender = case 
    ->                                when gender='M' then 'F' 
    ->                                when gender='F' then 'M'
    ->                                end
    -> WHERE gender IN ('M', 'F');
Query OK, 7 rows affected (0.00 sec)
Rows matched: 7  Changed: 7  Warnings: 0

mysql> 
mysql> select * from genderswap;
+--------+
| gender |
+--------+
| M      |
| M      |
| F      |
| F      |
| F      |
| F      |
| F      |
+--------+
7 rows in set (0.00 sec)

mysql> 

2

我将使用带有case表达式的更新。

DECLARE @Test TABLE
    (
      Name VARCHAR(100) NULL
    , Gender CHAR(1) NULL
    );

INSERT  INTO @Test
        ( Name, Gender )
VALUES  ( 'Jonathan', 'W' )
         ,
        ( 'Kelly', 'M' );

SELECT  Name
      , Gender
FROM    @Test;

UPDATE  @Test
SET     Gender = CASE WHEN Gender = 'M' THEN 'W'
                      ELSE 'M'
                 END;

SELECT  Name
      , Gender
FROM    @Test;

-1

您可以使用case表达式执行此更新。

UPDATE names_table
   SET names_table.gender = ( CASE
                                  WHEN names_table.gender = 'M'
                                    THEN 'W'
                                  ELSE
                                      names_table.gender = 'M'
                              END)

我建议在事务中运行您的更新语句,并添加一个简单的查询,例如:

SELECT n.gender, *
FROM names_table

为了检查结果,您会得到。当结果符合您的期望时,使用回滚执行事务并将其切换为提交。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.