2010-07-13 12 views
13

Ho una tabella precedente con circa 100 colonne (90% annullabili). In quelle 90 colonne voglio rimuovere tutte le stringhe vuote e impostarle su null. So che posso:Come faccio a modificare tutte le stringhe vuote su NULL in una tabella?

update table set column = NULL where column = ''; 
update table set column2 = NULL where column2 = ''; 

Ma questo è noioso e soggetto a errori. Ci deve essere un modo per farlo su tutto il tavolo?

+1

È questo un affare one-shot o sarà questa necessità di essere sempre? –

+0

one-shot, sarebbe prob. eseguirlo anche un'altra volta. –

+0

Stavo per suggerire che, se c'è il pericolo che le stringhe di lunghezza zero trovino nuovamente la loro strada nella tabella, è possibile creare una vista in cui le stringhe di lunghezza zero vengono convertite in valori NULL. In questo modo le tue applicazioni non dovrebbero mai preoccuparsi di loro. –

risposta

30
UPDATE 
    TableName 
SET 
    column01 = CASE column01 WHEN '' THEN NULL ELSE column01 END, 
    column02 = CASE column02 WHEN '' THEN NULL ELSE column02 END, 
    column03 = CASE column03 WHEN '' THEN NULL ELSE column03 END, 
    ..., 
    column99 = CASE column99 WHEN '' THEN NULL ELSE column99 END 

questo è ancora farlo manualmente, ma è leggermente meno doloroso di quello che hai, perché non richiede di inviare una query per ogni colonna. A meno che non vogliate prendere il disturbo di scriverlo, dovrete fare una certa quantità di dolore quando fate qualcosa del genere.

Edit: Aggiunta la sceneggiatura END s

+0

@OMG: perché? Presumibilmente, ti stai riferendo al nome della colonna END colonna ELSE, ma perché preoccuparti di TRIM? –

+0

@Jonathan Leffler: Questo è ciò che intendevo: 'CASE TRIM (column01) WHEN '' ... 'Avrei dovuto essere più chiaro che intendevo il paragone, mi dispiace. –

+0

@OMG: OK - Ora so cosa intendevi, ma ripeto la mia domanda: perché? Qual è il possibile vantaggio del taglio rispetto al semplice confronto con una stringa vuota? È probabile che il DBMS finisca per eseguire il riempimento vuoto della stringa tagliata perché il valore tagliato potrebbe essere lungo quanto il valore non modificato, quindi si sta solo facendo in modo che lavori vacui che potrebbero o meno individuare sono vuoti. –

0

penso che avrete bisogno di tirare ogni riga in un linguaggio come C#, php, ecc

Qualcosa di simile:

rows = get-data() 
foreach row in rows 
    foreach col in row.cols 
     if col == '' 
      col = null 
     end if 
    next 
next 
save-data() 
+0

Funzionerà, ma è fattibile in T-SQL usando un ciclo (ad esempio usando i cursori) sull'elenco di colonne. Per un compito di una volta, suppongo che in realtà non importa come lo fai, però. – Brian

+0

Tendo a gravitare lontano da SQL per questo tipo di manutenzione, poiché nella maggior parte dei casi finisco per dover aggiungere più funzionalità nel tempo, e finisco per trascinarlo in un linguaggio OO completo comunque. Ma questo è un pregiudizio personale ...;) – Nate

1

Non esiste un modo standard - ma si può interrogare il catalogo di sistema per ottenere i nomi delle colonne rilevanti per la tabella pertinente e generare l'SQL per farlo. È anche possibile utilizzare un'espressione CASE per gestire tutte le colonne in un unico passaggio: un'istruzione SQL più grande.

UPDATE Table 
    SET Column1 = CASE Column1 = ' ' THEN NULL ELSE Column1 END, 
     ... 

Si noti che una volta generata la grande istruzione UPDATE, tutto il lavoro viene eseguito nel server. Questo è molto più efficiente della selezione dei dati all'applicazione client, cambiandola lì e scrivendo il risultato sul database.

10

Una possibile:

for col in $(echo "select column_name from information_schema.columns 
where table_name='$TABLE'"|mysql --skip-column-names $DB) 
do 
echo update $TABLE set $col = NULL where $col = \'\'\; 
done|mysql $DB 
+0

+1 Ora è davvero bello! :) –

+1

Sì, non fare nulla che puoi convincere il tuo computer a fare per te ... :) – GalacticCowboy

+1

Non sicuro. Anche la clausola where ha bisogno di 'e table_schema = '$ SCHEMA''. –

5

Per i neofiti, si può ancora bisogno più lavoro dopo aver visto le risposte di cui sopra. E non è realistico digitare migliaia di righe. Così qui ho fornire un codice di lavoro completo per permettere di evitare errori di sintassi, ecc

DROP PROCEDURE IF EXISTS processallcolumns; 

DELIMITER $$ 

CREATE PROCEDURE processallcolumns() 
BEGIN 

    DECLARE i,num_rows INT ; 
    DECLARE col_name char(250); 

    DECLARE col_names CURSOR FOR 
    SELECT column_name 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE table_name = 'PROCESSINGTABLE' 
    ORDER BY ordinal_position; 

    OPEN col_names ; 
    select FOUND_ROWS() into num_rows; 

    SET i = 1; 
    the_loop: LOOP 

    IF i > num_rows THEN 
      CLOSE col_names; 
      LEAVE the_loop; 
     END IF; 


     FETCH col_names 
     INTO col_name;  


     SET @command_text = CONCAT('UPDATE `PROCESSINGTABLE` SET ', col_name, '= IF(LENGTH(', col_name, ')=0, NULL,', col_name, ') WHERE 1 ;') ; 

--  UPDATE `PROCESSINGTABLE` SET col_name=IF(LENGTH(col_name)=0,NULL,col_name) WHERE 1; 
--  This won't work, because MySQL doesn't take varibles as column name. 

     PREPARE stmt FROM @command_text ; 
     EXECUTE stmt ; 

     SET i = i + 1; 
    END LOOP the_loop ; 



END$$ 
DELIMITER ; 

call processallcolumns(); 
DROP PROCEDURE processallcolumns; 
Problemi correlati