約100列(90%null許容)のレガシーテーブルがあります。これらの90列で、すべての空の文字列を削除してnullに設定します。自分ができるということがわかっている:
update table set column = NULL where column = '';
update table set column2 = NULL where column2 = '';
しかし、それは面倒でエラーが発生しやすいものです。テーブル全体でこれを行う方法が必要ですか?
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
これはまだ手動で実行していますが、列ごとにクエリを送信する必要がないため、手間が少し少なくなります。スクリプトを作成する手間をかけたくない場合を除いて、このようなことを行うときは、ある程度の苦痛に耐えなければなりません。
編集:END
sを追加しました
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
初心者の場合、上記の回答を見た後でも、さらに作業が必要になる場合があります。そして、何千行も入力するのは現実的ではありません。そこで、ここでは、構文エラーなどを回避するための完全に機能するコードを提供します。
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;
標準的な方法はありませんが、システムカタログに問い合わせて、関連するテーブルの関連する列名を取得し、それを実行するSQLを生成することができます。また、CASE式を使用して、1回のパスですべての列を処理することもできます。これはより大きなSQLステートメントです。
UPDATE Table
SET Column1 = CASE Column1 = ' ' THEN NULL ELSE Column1 END,
...
大きなUPDATEステートメントを生成すると、すべての作業がサーバーで行われることに注意してください。これは、クライアントアプリケーションにデータを選択し、そこで変更して、結果をデータベースに書き戻すよりもはるかに効率的です。
単純な関数を記述して、それに列を渡すことができます。
使用法:
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 ;
各行をC#、phpなどの言語にプルする必要があると思います。
何かのようなもの:
rows = get-data()
foreach row in rows
foreach col in row.cols
if col == ''
col = null
end if
next
next
save-data()