Mysql 动态更改其中的 table 时调用过程失败
Mysql calling procedure failed when dynamically alter table in it
我想根据 table 是否有特定列动态更改我的 table。
我的数据库名称是summer_cms
,里面有50多个table。
我想要的是:
- 如果 table 有一个名为
add_time
的列,那么我想在其中添加一个列 add_user_id
。
- 同样,如果找到
update_time
,我想在 table 中添加 update_user_id
。
我知道我应该在创建数据库模式的过程中把它记下来,但是我的数据库已经建立了,我必须根据需要改变它。
所以我创建了一个程序来完成它:
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
但是我在调用这个过程时出错了。
Procedure execution failed
1146 - Table 'summer_cms.tableName' doesn't exist
谁能告诉我我遗漏了什么或错了什么?任何帮助将不胜感激。
您可以对您的程序进行一些改动,使其更加精简并解决一些问题。
首先使用光标 select table 名称,而不是使用您使用的两个 select。其次使用准备好的语句允许您动态设置 table 名称...
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 ;
您可以做一些调整 - 例如,只获取 table 列尚不存在的名称。
下面是一个动态的例子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 ;
注意我使用了 ascii 反引号和单引号。
我想根据 table 是否有特定列动态更改我的 table。
我的数据库名称是summer_cms
,里面有50多个table。
我想要的是:
- 如果 table 有一个名为
add_time
的列,那么我想在其中添加一个列add_user_id
。 - 同样,如果找到
update_time
,我想在 table 中添加update_user_id
。
我知道我应该在创建数据库模式的过程中把它记下来,但是我的数据库已经建立了,我必须根据需要改变它。
所以我创建了一个程序来完成它:
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
但是我在调用这个过程时出错了。
Procedure execution failed
1146 - Table 'summer_cms.tableName' doesn't exist
谁能告诉我我遗漏了什么或错了什么?任何帮助将不胜感激。
您可以对您的程序进行一些改动,使其更加精简并解决一些问题。
首先使用光标 select table 名称,而不是使用您使用的两个 select。其次使用准备好的语句允许您动态设置 table 名称...
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 ;
您可以做一些调整 - 例如,只获取 table 列尚不存在的名称。
下面是一个动态的例子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 ;
注意我使用了 ascii 反引号和单引号。