wintermeyer
wintermeyer

Reputation: 8318

Loop through all tables and rename a column

A client gave me a legacy database old_data which contains a bunch of tables which I'm going to activate in a new system step by step. Unfortunately a couple of the tables contain a column with the name hash which doesn't float well with Ruby on Rails which I use to tackle this project.

Is there a way to tell MySQL (version 8.0.12) in the MySQL console to loop through all tables in the given database and rename the column hash to old_hash if that column exists?

Upvotes: 4

Views: 801

Answers (1)

Matt Raines
Matt Raines

Reputation: 4218

Luckily MySQL 8 comes with an ALTER TABLE RENAME COLUMN a TO b syntax so you can write a reasonably straightforward stored procedure to do this.

DELIMITER //

CREATE PROCEDURE rename_columns(IN name_of_database CHAR(64),
                                IN old_name_of_column CHAR(64),
                                IN new_name_of_column CHAR(64))
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE name_of_table CHAR(64);
    DECLARE table_cursor CURSOR FOR
        SELECT TABLE_NAME FROM information_schema.COLUMNS
        WHERE TABLE_SCHEMA = name_of_database AND COLUMN_NAME = old_name_of_column;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    OPEN table_cursor;
    table_loop: LOOP
        FETCH table_cursor INTO name_of_table;
        IF done THEN LEAVE table_loop; END IF;
        SET @alter_sql = CONCAT(
            'ALTER TABLE ', name_of_database, '.', name_of_table,
            ' RENAME COLUMN ', old_name_of_column, ' TO ', new_name_of_column);
        PREPARE alter_statement FROM @alter_sql;
        EXECUTE alter_statement;
        DEALLOCATE PREPARE alter_statement;
    END LOOP;
    CLOSE table_cursor;
END//

DELIMITER ;

CALL rename_columns('old_data', 'hash', 'old_hash');

It's more complicated in 5.7 and earlier because you'll need to generate an ALTER TABLE CHANGE a b ... statement which includes the full column definition.

Upvotes: 2

Related Questions