web-dev-qa-db-ja.com

テーブル内のすべての空の文字列をNULLに変更するにはどうすればよいですか?

約100列(90%null許容)のレガシーテーブルがあります。これらの90列で、すべての空の文字列を削除してnullに設定します。自分ができるということがわかっている:

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

しかし、それは面倒でエラーが発生しやすいものです。テーブル全体でこれを行う方法が必要ですか?

17
Kyle West
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

これはまだ手動で実行していますが、列ごとにクエリを送信する必要がないため、手間が少し少なくなります。スクリプトを作成する手間をかけたくない場合を除いて、このようなことを行うときは、ある程度の苦痛に耐えなければなりません。

編集:ENDsを追加しました

40
Hammerite

1つの可能なスクリプト:

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
11

初心者の場合、上記の回答を見た後でも、さらに作業が必要になる場合があります。そして、何千行も入力するのは現実的ではありません。そこで、ここでは、構文エラーなどを回避するための完全に機能するコードを提供します。

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;
6
tomriddle_1234

標準的な方法はありませんが、システムカタログに問い合わせて、関連するテーブルの関連する列名を取得し、それを実行するSQLを生成することができます。また、CASE式を使用して、1回のパスですべての列を処理することもできます。これはより大きなSQLステートメントです。

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

大きなUPDATEステートメントを生成すると、すべての作業がサーバーで行われることに注意してください。これは、クライアントアプリケーションにデータを選択し、そこで変更して、結果をデータベースに書き戻すよりもはるかに効率的です。

1

単純な関数を記述して、それに列を渡すことができます。

使用法:

SELECT
  fn_nullify_if_empty(PotentiallyEmptyString)
FROM
  table_name
;

実装:

DELIMITER $$
CREATE FUNCTION fn_nullify_if_empty(in_string VARCHAR(255))
  RETURNS VARCHAR(255)
  BEGIN
    IF in_string = ''
      THEN RETURN NULL;
      ELSE RETURN in_string;
    END IF;
  END $$
DELIMITER ;
0
Nae

各行をC#、phpなどの言語にプルする必要があると思います。

何かのようなもの:

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