Cambio di valori in una colonna con un'istruzione di aggiornamento


12

Si scopre che un errore in un sistema ha erroneamente assegnato un nome a uomini (M) come donne (W) e viceversa nel database. Le colonne consentono solo un carattere. Senza utilizzare alcuna tabella temporanea, scrivere una query di aggiornamento per risolvere il problema.

Questa domanda è stata posta in una recente intervista che ho avuto, e vado in più interviste che potrebbero avere domande simili, quindi volevo avere un'idea di come gestirlo.


6
Ti è stato chiesto di assumere un determinato prodotto di database? ad es. MySQL, SQL Server, Oracle, PostgreSQL ...?
Paul White 9

Il tuo sistema ha letto le nuove linee guida della community? : \
AER il

Risposte:


22

Vuoi usare CASEun'espressione di qualche tipo.

In SQL Server il codice sarebbe simile al seguente:

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

Modifica: come indicato nei commenti (e in alcune delle altre risposte) l'ELSE non è necessario se si inserisce una clausola WHERE sull'istruzione.

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

Questo evita aggiornamenti inutili. La cosa importante in entrambi i casi è ricordare che esistono opzioni diverse da M & W (NULL per esempio) e che non si desidera inserire informazioni errate. Per esempio:

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

Ciò sostituirà qualsiasi NULL (o altri possibili sessi) come 'M' che sarebbe errato.


Un paio di altre opzioni sarebbero

/*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' );

E un più conciso

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

1
Potresti sostituire il IIF()con IF()e funzionerebbe in MySQL;)
ypercubeᵀᴹ

9

In Oracle potresti usare un CASO come le altre risposte hanno:

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

Puoi anche usare un DECODE:

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

5

Per passare da solo due valori, puoi anche provare questo trucco, che non usa CASEun'espressione (supponendo Transact-SQL qui):

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

A seconda del valore corrente di Gender, ASCII(Gender)verrà annullato uno ASCII('M')o ASCII('W'), lasciando l'altro codice per essere trasformato dalla CHAR()funzione al carattere corrispondente.

Lascio questo solo per confronto, però. Sebbene questa opzione possa avere una pretesa di eleganza, una soluzione che usa CASEun'espressione sarebbe probabilmente più leggibile e quindi più facile da mantenere, e sarebbe sicuramente più facile espandersi a più di due valori.


2
Speriamo che tutti Me siano Wstati inseriti in 7lettere maiuscole per evitare imprevisti o `-` apparire nei risultati.
Martin Smith,

@MartinSmith: ottimo punto. Se non lo fossero, dovremo sostituirlo ASCII(Gender)con ASCII(UPPER(Gender)), che è meno elegante, anche se non molto.
Andriy M,

@MartinSmith se ci sono lettere minuscole m e w, non saranno respinte dalla WHEREclausola?
ypercubeᵀᴹ

1
@ YperSillyCubeᵀᴹ - Solo in casi sensibili (che non sono il solito IME)
Martin Smith

4

Puoi farlo con case ... whenun'espressione:

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

Vorrei usare un aggiornamento con caseun'espressione.

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

È possibile eseguire questo aggiornamento utilizzando caseun'espressione.

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

Suggerirei di eseguire la tua dichiarazione di aggiornamento all'interno di una transazione e di aggiungere una semplice query come:

SELECT n.gender, *
FROM names_table

per verificare i risultati che otterrai. Esecuzione della transazione con un rollback e passaggio a un commit quando i risultati si allineano con ciò che ti aspetti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.