Rename column for all tables in mysql database - mysql

I need to rename column for all tables in my databse.
I could get list of columns using this query:
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME= <Column Name>;
But how actually I could rename it as simple as possible and do not write
ALTER TABLE <Table Name >RENAME COLUMN <Old name> to <New Name>;
for each table.
I've tried to write a procedure:
DELIMITER $$
DROP PROCEDURE IF EXISTS renameColumn $$
CREATE PROCEDURE renameColumn(IN oldName tinytext, IN newName tinytext)
BEGIN
DECLARE #name VARCHAR(255);
DECLARE exit_loop BOOLEAN;
DECLARE tableName_cursor CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME=oldName;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
OPEN tableName_cursor;
rename_loop: LOOP
FETCH tableName_cursor #name;
ALTER TABLE #name RENAME COLUMN oldName to newName;
IF exit_loop THEN
LEAVE rename_loop;
END IF;
END LOOP rename_loop;
END $$
DELIMITER;
But I have the following error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '#name VARCHAR(255);
DECLARE exit_loop BOOLEAN;
DECLARE ta' at line 3
Could you please help me to resolve this issue

You can try this.
SELECT CONCAT(
'ALTER TABLE ', TABLE_NAME,
' RENAME COLUMN ', COLUMN_NAME,
' NEW_', COLUMN_NAME,
';') AS rename_script
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'your_db'

Try the following solution hope it will help
DECLARE #name VARCHAR(50) -- database name
DECLARE db_cursor CURSOR FOR
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME= 'OldColumn';
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
set #name = #name + '.OldColumn'
EXEC sp_rename #name, 'NewColumn', 'COLUMN';
print(#name)
FETCH NEXT FROM db_cursor INTO #name
END
CLOSE db_cursor
DEALLOCATE db_cursor

Related

Mysql calling procedure failed when dynamically alter table in it

I want to alter my tables dynamically based on whether the table has specific column.
My database name is summer_cms, and there are over 50 tables in it.
What I want are below:
If a table has a column named add_time, then I would like to add a column add_user_id in it.
Similarly, I would like to add update_user_id in the table if update_time is found.
I know I should get it down in the process of creating the database schemas, but my database has been built and I have to alter it by need.
So I create a procedure to do it:
CREATE PROCEDURE ALTER_SUMMER_TABLE()
BEGIN
DECLARE tableName VARCHAR(64);
DECLARE exitence VARCHAR(64);
DECLARE ntable INT; # number of tables
DECLARE i INT; # index
SET i = 0;
# get the count of table
SELECT COUNT(DISTINCT(TABLE_NAME)) INTO ntable FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'summer_cms';
WHILE i < ntable DO
# select the specific table name into the variable of `tableName`.
SELECT TABLE_NAME INTO tableName
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'summer_cms'
AND COLUMN_NAME = 'add_time'
LIMIT 1 OFFSET i;
# alter table, but I get error in this clause.
ALTER TABLE tableName ADD COLUMN `add_user_id` INT NOT NULL DEFAULT 0 COMMENT 'add user id';
# check if the table has `update_time`
SELECT TABLE_NAME INTO exitence
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'summer_cms'
AND TABLE_NAME = tableName
AND COLUMN_NAME = 'update_time';
# add `update_user_id` if `update_time` be found.
IF exitence THEN
ALTER TABLE tableName ADD COLUMN `update_user_id` INT NOT NULL DEFAULT 0 COMMENT 'update user id';
END IF;
SET i = i + 1;
END WHILE;
END
But I got an error when I call this procedure.
Procedure execution failed
1146 - Table 'summer_cms.tableName' doesn't exist
Dose anyone could tell me what I was missing or wrong? Any help will be appreciated.
There a a few alterations you can make to your procedure to make it more streamlined as well as getting round a few problems.
First using a cursor to select the table names rather than using the two selects your using. Secondly to use a prepared statement to allow you to dynamically set the table name...
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `ALTER_SUMMER_TABLE`()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE tableName VARCHAR(64);
declare cur cursor for SELECT TABLE_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'summer_cms'
AND COLUMN_NAME = 'add_time';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
open cur;
start_loop: loop
fetch cur into tableName;
if (done = 1 )THEN
LEAVE start_loop;
END IF;
SET #sql = CONCAT('ALTER TABLE ', tableName,' ADD COLUMN `add_user_id` INT NOT NULL DEFAULT 0 ');
PREPARE stmt FROM #sql;
EXECUTE stmt;
end loop;
close cur;
END$$
DELIMITER ;
You could do a few tweaks - only fetch table names where the column doesn't already exist for example.
Here's an example of dynamic sql
drop procedure if exists alter_table;
delimiter //
CREATE DEFINER=`root`#`localhost` procedure alter_table()
begin
declare tablename varchar(20);
set tablename = 'u';
set #sqlstmt = concat('ALTER TABLE ', tableName, ' ADD COLUMN ', char(96), 'add_user_id', char(96), ' INT NOT NULL DEFAULT 0 COMMENT', char(39), 'add user id', char(39),';');
prepare stmt from #sqlstmt;
execute stmt;
deallocate prepare stmt;
end //
delimiter ;
Note I have used ascii backticks and single quotes.

mysql stored procedure to alter column type

In my MySQL setup I have about a dozen database with hundreds of tables where all id fields are defined with type varchar(20). Per database there are a few thousand of these fields. These fields need to be altered into varchar(36).
In order to make this happen I have created a stored procedure, that:
gets all appropriate schemas;
get the tables of the schemas;
loop through all the columns and when the column type = 'varchar(20) alter the column to varchar(36).
The content of the procedure is available below. But instead of altered column types I get nothing. Meaning there is something wrong. But what is it?
Can you help me out?
DELIMITER $$
DROP PROCEDURE IF EXISTS `get_database`$$
DROP PROCEDURE IF EXISTS `get_table`$$
DROP PROCEDURE IF EXISTS `get_column`$$
DROP PROCEDURE IF EXISTS `alter_column`$$
CREATE PROCEDURE get_database()
BEGIN
DECLARE db_rows INT;
DECLARE dbI INT DEFAULT 1;
DECLARE db_name VARCHAR(255);
DECLARE db_names CURSOR FOR SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME LIKE '%ofb%';
SET #enabled = TRUE;
select FOUND_ROWS() into db_rows;
open db_names;
db_loop: LOOP
if dbI > db_rows THEN
CLOSE db_names;
LEAVE db_loop;
end if;
FETCH db_names INTO db_name;
-- database found
if db_name then
call get_table(db_name);
end if;
SET #dbI = #dbI + 1;
END LOOP db_loop;
END $$
CREATE PROCEDURE get_table(db_name VARCHAR(255))
BEGIN
DECLARE tn_rows INT;
DECLARE tnI INT DEFAULT 1;
DECLARE table_name VARCHAR(255);
DECLARE table_names CURSOR FOR SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = db_name;
SET #enabled = TRUE;
SET tnI = 1;
SET #enabled = TRUE;
select FOUND_ROWS() into tn_rows;
open table_names;
table_loop: LOOP
if tnI > tn_rows THEN
CLOSE table_names;
LEAVE table_loop;
end if;
FETCH table_names INTO table_name;
-- table_name found
if table_name then
call get_column(db_name, table_name);
end if;
SET tnI = tnI + 1;
END LOOP table_loop;
END $$
CREATE PROCEDURE get_column(db_name VARCHAR(255), table_name VARCHAR(255))
BEGIN
DECLARE cn_rows INT;
DECLARE cnI INT DEFAULT 1;
DECLARE column_name VARCHAR(255);
DECLARE column_names
CURSOR FOR SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = db_name and TABLE_SCHEMA = table_name;
SET #enabled = TRUE;
SET cnI = 1;
select FOUND_ROWS() into cn_rows;
open column_names;
column_loop: LOOP
if cnI > nn_rows THEN
CLOSE column_names;
LEAVE column_loop;
end if;
FETCH column_names INTO column_name;
-- column_name found
if column_name then
call alter_column(db_name, table_name, column_name);
end if;
SET cnI = cnI + 1;
END LOOP column_loop;
END $$
CREATE PROCEDURE alter_column(db_name VARCHAR(255), table_name VARCHAR(255), column_name VARCHAR(255))
BEGIN
DECLARE dtype VARCHAR(255);
declare data_type
CURSOR FOR SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = table_name and TABLE_NAME = table_name AND COLUMN_NAME = column_name;
open data_type;
fetch data_type into dType;
if dType = 'varchar(20)' then
SET #ddl = CONCAT('alter table ', db_name, '.',table_name, ' modify column (', column_name, ' VARCHAR(36))');
PREPARE STMT FROM #ddl;
EXECUTE STMT;
end if;
END $$
DELIMITER ;
Your help is appreciated.
Best regards
I was in need of these procedures, and see some changes I made, that worked:
CREATE PROCEDURE get_database()
BEGIN
DECLARE _table_name VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE table_names CURSOR FOR
SELECT table_name
FROM INFORMATION_SCHEMA.TABLES WHERE
TABLE_SCHEMA like '%ofb%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN table_names;
table_loop: LOOP
FETCH table_names INTO _table_name;
IF finished = 1 THEN
CLOSE table_names;
LEAVE table_loop;
END IF;
CALL get_column('%ofb%', _table_name);
END LOOP table_loop;
END
CREATE PROCEDURE get_column(db_name VARCHAR(255), table_name VARCHAR(255))
BEGIN
DECLARE _column_name VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE column_names CURSOR FOR
SELECT column_name FROM
INFORMATION_SCHEMA.COLUMNS
WHERE table_schema LIKE db_name AND
TABLE_NAME = _table_name AND
DATA_TYPE = "varchar" AND
CHARACTER_MAXIMUM_LENGTH = 20
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN column_names;
column_loop: LOOP
FETCH column_names INTO _column_name;
IF finished = 1 THEN
CLOSE column_names;
LEAVE column_loop;
END IF;
SET #ddl = CONCAT('ALTER TABLE ', db_name, '.',_table_name, ' MODIFY COLUMN ', _column_name, ' VARCHAR(36) NULL');
PREPARE STMT FROM #ddl;
EXECUTE STMT;
END LOOP column_loop;
END

How to update column in every table which name starts with special characters

I need to update special column in every table that which name start with :-
`REPORT_<"DATE PATERN">`
How actually I can do it?.
upd:
I've tried to write stored procedure, but I'm not familiar with it, so it does not work:
DELIMITER $$
DROP PROCEDURE IF EXISTS `debug_msg`$$
CREATE PROCEDURE debug_msg(enabled INTEGER, msg VARCHAR(255))
BEGIN
IF enabled THEN BEGIN
select concat("** ", msg) AS '** DEBUG:';
END; END IF;
END $$
DELIMITER $$
DROP PROCEDURE IF EXISTS changeColumnType;
CREATE PROCEDURE changeColumnType ()
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE tableName varchar(100);
DEClARE table_cursor CURSOR FOR
SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME LIKE '%REPORT_%';
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
OPEN table_cursor;
get_tableName: LOOP
FETCH table_cursor INTO tableName;
IF v_finished = 1 THEN
LEAVE get_tableName;
END IF;
call debug_msg(1, tableName);
ALTER TABLE tableName MODIFY COLUMN TIME VARCHAR(8);
END LOOP get_tableName;
CLOSE table_cursor;
END$$
DELIMITER ;
I have the following error:
ERROR 1146 (42S02): Table 'test.tablename' doesn't exist.
I fails on this step ALTER TABLE tableName MODIFY COLUMN TIME VARCHAR(8);
Resolved it by adding prepared statement
SET #table = tableName;
SET #s1 = CONCAT('ALTER TABLE ', #table, ' MODIFY COLUMN TIME VARCHAR(8);');
PREPARE stmt FROM #s1;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Mysql error in stored procudure

This stored procedure is to search through all tables and columns in database.
DELIMITER $$
DROP PROCEDURE IF EXISTS get_table $$
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
PROCEDURE `auradoxdb`.`get_table`(in_search varchar(50))
READS SQL DATA
BEGIN
DECLARE trunc_cmd VARCHAR(50);
DECLARE search_string VARCHAR(250);
DECLARE db,tbl,clmn CHAR(50);
DECLARE done INT DEFAULT 0;
DECLARE COUNTER INT;
DECLARE table_cur CURSOR FOR
SELECT concat(SELECT COUNT(*) INTO #CNT_VALUE
FROM `’,table_schema,’`.`’, table_name,’`
WHERE `’, column_name,’` REGEXP ”’,in_search,”’
)
, table_schema
, table_name
, column_name
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA NOT IN (‘information_schema’,'test’,'mysql’);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
# #Truncating table for refill the data for new search.
PREPARE trunc_cmd FROM “TRUNCATE TABLE temp_details;”
EXECUTE trunc_cmd ;
OPEN table_cur;
table_loop:LOOP
FETCH table_cur INTO search_string,db,tbl,clmn;
# #Executing the search
SET #search_string = search_string;
SELECT search_string;
PREPARE search_string FROM #search_string;
EXECUTE search_string;
SET COUNTER = #CNT_VALUE;
SELECT COUNTER;
IF COUNTER>0 THEN
# # Inserting required results from search to tablehhh
INSERT INTO temp_details VALUES(db,tbl,clmn);
END IF;
IF done=1 THEN
LEAVE table_loop;
END IF;
END LOOP;
CLOSE table_cur;
# #Finally Show Results
SELECT * FROM temp_details;
END $$
DELIMITER ;
Following error occurs when execute this..
Error Code : 1064
You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near 'SELECT COUNT(*)
INTO #CNT_VALUE FROM `’,table_schema,’`.`’,table_name,’`' at line 12
(0 ms taken)
could any body please help me to solve this?
It appears that you are trying to dynamically build an SQL statement for each table. To do this, you will need to quote the text parts as if it was a normal string and concatenate the dynamic parts. Replacing the query with the following should work:
SELECT concat('SELECT COUNT(*) INTO #CNT_VALUE FROM ',
table_schema,'.', table_name,
' WHERE ', column_name,' REGEXP ''',in_search,''''
)
, table_schema
, table_name
, column_name
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA NOT IN ('information_schema','test','mysql');

Error when calling Mysql Stored procedure

This is my stored procedure to search throgh all databases,tables and columns.
This procedure got created with out any error.
DELIMITER $$
DROP PROCEDURE IF EXISTS `mydb`.`get_table`$$
CREATE DEFINER=`root`#`%` PROCEDURE `get_table`(in_search varchar(50))
READS SQL DATA
BEGIN
DECLARE trunc_cmd VARCHAR(50);
DECLARE search_string VARCHAR(250);
DECLARE db,tbl,clmn CHAR(50);
DECLARE done INT DEFAULT 0;
DECLARE COUNTER INT;
DECLARE table_cur CURSOR FOR
SELECT concat('SELECT COUNT(*) INTO #CNT_VALUE FROM ',
table_schema,'.', table_name,
' WHERE ', column_name,' REGEXP ''',in_search,''''
)
,table_schema,table_name,column_name
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA NOT IN ('mydb','information_schema');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
# #Truncating table for refill the data for new search.
PREPARE trunc_cmd FROM 'TRUNCATE TABLE temp_details';
EXECUTE trunc_cmd ;
OPEN table_cur;
table_loop:LOOP
FETCH table_cur INTO search_string,db,tbl,clmn;
# #Executing the search
SET #search_string = search_string;
SELECT search_string;
PREPARE search_string FROM #search_string;
EXECUTE search_string;
SET COUNTER = #CNT_VALUE;
SELECT COUNTER;
IF COUNTER>0 THEN
# # Inserting required results from search to table
INSERT INTO temp_details VALUES(db,tbl,clmn);
END IF;
IF done=1 THEN
LEAVE table_loop;
END IF;
END LOOP;
CLOSE table_cur;
# #Finally Show Results
SELECT * FROM temp_details;
END$$
DELIMITER ;
But when calling this procedure following error occurs.
call get_table('aaa')
Error Code : 1064 You have an error in
your SQL syntax; check the manual that
corresponds to your MySQL server
version for the right syntax to use
near 'delete REGEXP 'aaa'' at line 1
(0 ms taken)
Where does "delete" come from? Do you have a column_name with that name? If so, use better names, not reserved ones, or use nasty backticks ` or ANSI-quotes " around the column name.
Constructions like this are vulnerable to SQL injection.