How do I change all empty strings to NULL in a table?
I have a legacy table with about 100 columns (90% nullable). In those 90 columns I want to remove all empty strings and set them to null. I know I can:
update table set column = NULL where column = '';
update table set column2 = NULL where column2 = '';
Bu开发者_如何学Ct that is tedious and error prone. There has to be a way to do this on the whole table?
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
This is still doing it manually, but is slightly less painful than what you have because it doesn't require you to send a query for each and every column. Unless you want to go to the trouble of scripting it, you will have to put up with a certain amount of pain when doing something like this.
Edit: Added the END
s
One possible script:
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
For newbies, you may still need more work after seeing the above answers. And it's not realistic to type thousands lines. So here I provide a complete working code to let you avoid syntax errors 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;
Hammerite's answer is good but you can also replace CASE
statements with IF
s.
UPDATE
TableName
SET
column01 = IF(column01 = '', NULL, column01),
column02 = IF(column02 = '', NULL, column02),
column03 = IF(column03 = '', NULL, column03),
...,
column99 = IF(column99 = '', NULL, column99)
There isn't a standard way - but you can interrogate the system catalog to get the relevant column names for the relevant table and generate the SQL to do it. You can also probably use a CASE expression to handle all the columns in a single pass - a bigger SQL statement.
UPDATE Table
SET Column1 = CASE Column1 = ' ' THEN NULL ELSE Column1 END,
...
Note that once you've generated the big UPDATE statement, all the work is done down in the server. This is much more efficient than selecting data to the client application, changing it there, and writing the result back to the database.
I think you'll need to pull each row into a language like C#, php, etc.
Something like:
rows = get-data()
foreach row in rows
foreach col in row.cols
if col == ''
col = null
end if
next
next
save-data()
You could write a simple function and pass your columns to it:
Usage:
SELECT
fn_nullify_if_empty(PotentiallyEmptyString)
FROM
table_name
;
Implementation:
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 ;
精彩评论