tags:

views:

73

answers:

5

Dear all,

i´d like to update all NULL fields in one table to 0. Of course

UPDATE mytable SET firstcol=0 WHERE firstcol IS NULL 

would do the job. But I wonder if there´s a smarter solution than just c&p this line for every column. Thx in advance for any suggestions

+2  A: 

Not without an intermediate technology or cursor. You could use DESCRIBE mytable; to get the column names and loop over them to build your UPDATE queries.

So it is possible. But by the time it took you to write that, you probably just could have copy and pasted ;)

Jason McCreary
I must admit, either I don´t get the answers or just posted badly. However, what Jason says was what I felt. I just wonder if there is a solution but a loop. I just did not need loops in SQL so far and thus have no experience :)
ran2
IMO, this is a trivial thing. Just run your statements by copy and paste. I do agree with the others though. If you started from scratch, you could have added a `DEFAULT 0` to your columns.
Jason McCreary
+1  A: 

You may want to alter your columns to NOT NULL.

ALTER TABLE your_table MODIFY COLUMN your_field INT NOT NULL;

Test case:

CREATE TABLE nulltable (id INT);

INSERT INTO nulltable VALUES (1);
INSERT INTO nulltable VALUES (2);
INSERT INTO nulltable VALUES (3);
INSERT INTO nulltable VALUES (NULL);
INSERT INTO nulltable VALUES (NULL);
INSERT INTO nulltable VALUES (NULL);
INSERT INTO nulltable VALUES (5);

Result:

mysql> SELECT * FROM nulltable;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
| NULL |
| NULL |
| NULL |
|    5 |
+------+
7 rows in set (0.00 sec)

mysql> ALTER TABLE nulltable MODIFY COLUMN id INT NOT NULL;
Query OK, 7 rows affected, 3 warnings (0.08 sec)
Records: 7  Duplicates: 0  Warnings: 3

mysql> SELECT * FROM nulltable;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  0 |
|  0 |
|  0 |
|  5 |
+----+
7 rows in set (0.00 sec)
Daniel Vassallo
ran2 may want to do that in the long run, but that shouldn't update rows that already exist. At least, I hope it doesn't update rows that already exist.
Brian Hooper
@Brian: It does :) ... (I think unless running in strict mode.)
Daniel Vassallo
Yes, this works. Note that you may receive the rather generic 'DATA TRUNCATED' warning, but nothing has really been truncated - it's just one of those [slightly misleading error messages](http://dev.mysql.com/doc/refman/5.1/en/faqs-cjk.html#qandaitem-24-11-1-1).
Mike
Oh dear. My illusions about SQL have been shattered...
Brian Hooper
@Brian Hooper: Other than a possible slight concern over MySQL not issuing a warning prior to making the change, this makes sense. NULL is ["a missing unknown value"](http://dev.mysql.com/doc/refman/5.1/en/working-with-null.html). When the column is changed to disallow null values, something has to go in their place.
Mike
+2  A: 

Can you just ALTER the columns to NOT NULL DEFAULT 0?

You can do this in a single statement, as per MySQL documentation:

You can issue multiple ADD, ALTER, DROP, and CHANGE clauses in a single ALTER TABLE statement, separated by commas. This is a MySQL extension to standard SQL, which allows only one of each clause per ALTER TABLE statement.

Piskvor
Hmm, the table is created with a create table mytable AS SELECT ... statement that contains cases. Somehow i was not able to set default values there. That´s why I ended up with the NULL values. If I alter that table i´d have to do it for every column separately which is exactly what I am trying to prevent.
ran2
@ran2: Not in MySQL you don't - edited to reflect this.
Piskvor
thx, obviously i did not know about this fact. Still, I wonder if i have to list all the columns in such an ALTER statement. I just want to do it for the whole table, because if I had 60 columns, it would ugly to list em all – no matter if in one or multiple statements.
ran2
@ran2: Yes, you have to list them all.
Piskvor
thanks Piskvor, good to know that. probably I am just a little spoiled by the functionality of R that allows to run functions on every column of a table.
ran2
A: 

I don't believe there is; any statement that worked on rows that didn't satisfy the where clause would update rows you didn't intent to update. Jason's answer is correct, but, I think, a bit unsafe, unless you are really sure that's what you want.

Brian Hooper
+2  A: 

You could do this - repeat as necessary for each column:

UPDATE `table1`  SET
    `col1` = IFNULL(col1, 0),
    `col2` = IFNULL(col2, 0);

Example:

DROP TABLE IF EXISTS `table1`;

CREATE TABLE `table1` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `col1` int(10) unsigned,
  `col2` int(10) unsigned,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB;

INSERT INTO `table1` VALUES
(1,    1, NULL),
(2, NULL, NULL),
(3,    2, NULL),
(4, NULL, NULL),
(5,    3,    4),
(6,    5,    6),
(7,    7, NULL);

UPDATE `table1`  SET
    `col1` = IFNULL(col1, 0),
    `col2` = IFNULL(col2, 0);

SELECT * FROM `table1`;

+----+------+------+
| id | col1 | col2 |
+----+------+------+
|  1 |    1 |    0 |
|  2 |    0 |    0 |
|  3 |    2 |    0 |
|  4 |    0 |    0 |
|  5 |    3 |    4 |
|  6 |    5 |    6 |
|  7 |    7 |    0 |
+----+------+------+

UPDATE

If you want to alter the table structure by changing columns so that they no longer accept nulls, you could do it with a stored procedure. The following stored procedure queries the INFORMATION_SCHEMA COLUMNS for information about columns in a given database table. From that information, it builds up a prepared statement which is then used to alter the table structure. You may need to tweak it to suit your exact requirements - at the moment, it looks for INT columns which do not have NOT NULL set:

delimiter //
DROP PROCEDURE IF EXISTS no_nulls//
CREATE PROCEDURE `no_nulls` (IN param_schema CHAR(255), IN param_table CHAR(255))
BEGIN

    SET @alter_cmd = (SELECT CONCAT(
        'ALTER TABLE ',
        param_table,
        GROUP_CONCAT(
            ' MODIFY COLUMN ',
            `column_name`, ' ',
            `column_type`,
            ' NOT NULL'
            SEPARATOR ', ')
        ) AS `sql_cmd`
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE `table_schema` = param_schema
    AND `table_name` = param_table
    AND LCASE(`data_type`) = 'int'
    AND LCASE(`is_nullable`) = 'yes');

    IF NOT ISNULL(@alter_cmd) THEN
        SELECT @alter_cmd;
        PREPARE stmt FROM @alter_cmd;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END IF;

END//
delimiter ;

Example:

CREATE TABLE `test`.`table1` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `col1` int(10) unsigned,
  `col2` int(10) unsigned,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB;

CALL no_nulls('test', 'table1');
    +----------------------------------------------------------------------------------------------------------------+
| @alter_cmd                                                                                                     |
+----------------------------------------------------------------------------------------------------------------+
| ALTER TABLE table1 MODIFY COLUMN col1 int(10) unsigned NOT NULL,  MODIFY COLUMN col2 int(10) unsigned NOT NULL |
+----------------------------------------------------------------------------------------------------------------+

SHOW CREATE TABLE `test`.`table1`;

CREATE TABLE `table1` (
    `id` int(10) unsigned NOT NULL auto_increment,
    `col1` int(10) unsigned NOT NULL,
    `col2` int(10) unsigned NOT NULL,
    PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

The following line displays the command that is to be executed, and may be removed from the stored procedure if necessary:

SELECT @alter_cmd;
Mike