Skip to content

Instantly share code, notes, and snippets.

@hosseinm1997
Last active September 26, 2017 05:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hosseinm1997/3bbbec3fc574287c752754db0201abfd to your computer and use it in GitHub Desktop.
Save hosseinm1997/3bbbec3fc574287c752754db0201abfd to your computer and use it in GitHub Desktop.
Procedure to convert string based fields collations and character sets to any.
# ===========> Start copying <=============#
DELIMITER //
CREATE PROCEDURE changeAllCollations(
db_name VARCHAR(100),
char_set VARCHAR(25),
collation_name VARCHAR(50),
prevent_key_too_long Boolean
)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE tbl_name VARCHAR(50);
DECLARE changes varchar(1000);
DECLARE cur_tables CURSOR FOR SELECT table_name FROM information_schema.tables where table_schema=db_name;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur_tables;
set changes = "";
read_loop: LOOP
FETCH cur_tables into tbl_name;
IF done THEN
LEAVE read_loop;
END IF;
set changes = CONCAT(changes,tbl_name,"\n");
BLOCK2: BEGIN
DECLARE table_done INT DEFAULT FALSE;
DECLARE col_name,col_type,col_maxlen VARCHAR(50);
DECLARE cur_columns CURSOR FOR SELECT COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE `TABLE_SCHEMA`=db_name AND `TABLE_NAME`=tbl_name AND (`DATA_TYPE`='varchar' OR `DATA_TYPE`='char' OR `DATA_TYPE`='tinytext' OR `DATA_TYPE`='text' OR `DATA_TYPE`='mediumtext' OR `DATA_TYPE`='longtext');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET table_done = TRUE;
OPEN cur_columns;
read_table_loop: LOOP
FETCH cur_columns into col_name,col_type,col_maxlen;
IF table_done THEN
CLOSE cur_columns;
LEAVE read_table_loop;
END IF;
# Tolerate the key too long error
# This should convert string data types maximum length to 191 which have unique indexes.
# See https://wildlyinaccurate.com/mysql-specified-key-was-too-long-max-key-length-is-767-bytes/
IF prevent_key_too_long AND col_maxlen > 191 THEN
SET col_maxlen=191;
END IF;
SET @query = CONCAT('ALTER TABLE ', tbl_name , ' Modify ', col_name , ' ' , col_type , '(' , col_maxlen ,') CHARACTER SET ' , char_set , ' COLLATE ' , collation_name , ';');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set changes = CONCAT(changes,tbl_name,".",col_name,", ");
END LOOP read_table_loop;
End BLOCK2;
SET @query = CONCAT('ALTER TABLE ', tbl_name , ' CONVERT TO CHARACTER SET ' , char_set , ' COLLATE ' , collation_name , ';');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set changes = CONCAT(changes,"\n");
END LOOP read_loop;
CLOSE cur_tables;
SELECT changes;
END//
# ===========> End copying <=============#
# Paste the contents into the sql tab of your database then run (Click Go) to make the procedure.
# To use proecdure just call the procedure like this :
call changeAllCollations('testdb','utf8mb4' , 'utf8mb4_unicode_ci' , true)
# Pls set the last parameter to true if your intended collation and character set are utf8mb4 based
# and your mysql version is older than 5.7.7, otherwise set it false.
# BE CAREFUL! By setting true, unique string based maximum length fields will be trimmed to 191.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment