2010-07-13 5 views
13

J'ai une table héritée avec environ 100 colonnes (90% nulle). Dans ces 90 colonnes, je veux supprimer toutes les chaînes vides et les mettre à null. Je sais que je peux:Comment modifier toutes les chaînes vides à NULL dans un tableau?

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

Mais cela est fastidieux et sujet aux erreurs. Il doit y avoir un moyen de faire cela sur toute la table?

+1

Est-ce une affaire one-shot ou sera ce besoin d'être maintenu? –

+0

one-shot, serait prob. exécutez-le un autre moment aussi bien. –

+0

J'allais suggérer que, s'il y a un risque que des chaînes de longueur zéro trouvent leur chemin dans la table, vous pourriez créer une vue dans laquelle les chaînes de longueur zéro sont converties en valeurs NULL. De cette façon, vos applications n'auront jamais à se soucier d'eux. –

Répondre

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 

Cela fait encore manuellement, mais est un peu moins douloureux que ce que vous avez, car il ne nécessite pas d'envoyer une requête pour chaque colonne. À moins que vous ne vouliez vous donner la peine de l'écrire, vous devrez supporter une certaine douleur en faisant quelque chose comme ça.

Edit: Ajout de la END s

+0

@OMG: pourquoi? Vraisemblablement, vous faites référence au nom de la colonne ELSE columnXX END, mais pourquoi s'embêter avec TRIM? –

+0

@Jonathan Leffler: C'est ce que je voulais dire: 'CASE TRIM (column01) WHEN '' ...' 'J'aurais dû être plus clair que je voulais dire la comparaison, désolé. –

+0

@OMG: OK - Je sais maintenant ce que vous vouliez dire, mais je réitère ma question: pourquoi? Quel est l'avantage possible de la coupe par rapport à la simple comparaison avec une chaîne vide? Il est probable que le SGBD finisse par faire un remplissage vide de la chaîne tronquée, car la valeur tronquée peut être aussi longue que la valeur non tronquée, de sorte que vous ne faites que faire un travail vide qui peut être vide ou non. –

0

Je pense que vous aurez besoin de tirer chaque ligne dans une langue comme C#, php, etc.

Quelque chose comme:

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

Cela fonctionnera, mais c'est possible dans T-SQL en utilisant une boucle (par exemple en utilisant des curseurs) sur la liste des colonnes. Pour une tâche ponctuelle, je suppose que cela n'a pas vraiment d'importance. – Brian

+0

J'ai tendance à m'éloigner de SQL pour ce type de maintenance, car dans la plupart des cas, je finis par devoir ajouter plus de fonctionnalités au fil du temps, et je finis par l'utiliser dans un langage OO complet. Mais c'est un parti pris personnel ...;) – Nate

1

Il n'y a pas un moyen standard - mais vous pouvez interroger le catalogue système pour obtenir les noms de colonne appropriés pour la table pertinente et générer le SQL pour le faire. Vous pouvez également utiliser probablement une expression CASE pour gérer toutes les colonnes en un seul passage - une instruction SQL plus importante.

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

Notez qu'une fois que vous avez généré la grande instruction UPDATE, tout le travail est effectué dans le serveur. C'est beaucoup plus efficace que de sélectionner des données dans l'application cliente, de les modifier et d'écrire le résultat dans la base de données.

10

Un scénario possible:

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 Maintenant c'est vraiment sympa! :) –

+1

Ouais, ne faites rien que vous pouvez convaincre votre ordinateur à faire pour vous ... :) – GalacticCowboy

+1

Pas sûr. La clause where a également besoin de 'et table_schema = '$ SCHEMA''. –

5

Pour les débutants, vous pouvez encore avoir besoin de plus de travail après avoir vu les réponses ci-dessus. Et ce n'est pas réaliste de taper des milliers de lignes. Donc ici, je fournir un code de travail complet pour vous permettre d'éviter les erreurs de syntaxe, etc.

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;