- 最近在项目中遇到了修改之前的表结构的问题,由于是使用jerkins自动打包成镜像放到PASS云上的,这样要求所有的SQL文件都是可以重复执行的,比如正常插入语句
insert into table_name (col1,col2) values (xxxxx,xxxxx);
- 但是到了这种环境就需要改成下面
replace into table_name (col1,col2) values (xxxxxx,xxxxxx);
因为要是重复执行的话就会插入多个记录了。
replace 会根据主键假如存在就替换,假如不存在则新增。但是到了修改表结构 (change,modify,add) 这些并不存在这么方便的 语句。这时候我们就可以使用到存储过程了。我们直接来看整个函数:
DROP PROCEDURE IF EXISTS `PROC_TEMP_ALTER_COL_SAFE`;
delimiter $$
CREATE PROCEDURE `PROC_TEMP_ALTER_COL_SAFE` (IN db VARCHAR (100),IN tb VARCHAR (100),IN col VARCHAR (100),
IN sqlForNoExits VARCHAR (100),in sqlForExits VARCHAR (100))
BEGIN
SET @sql :='';
if NOT exists(SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = db AND TABLE_NAME =tb AND COLUMN_NAME = col)
THEN
BEGIN
SET @sql = concat(' alter table ',tb,' ',sqlForNoExits);
END ;
ELSE
BEGIN
SET @sql = concat(' alter table ',tb,' ',sqlForExits);
END ;
END IF ;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
delimiter ;
sql DROP PROCEDURE IF EXISTS `PROC_TEMP_ALTER_COL_SAFE`;
清除原有的存储过程;
delimiter $$
就是定义结束符为 $$ 最主要是和存储过程的;区分开来。
输入参数中 db
代表 数据库名 tb
数据库名 col
列名 sqlForNoExits
假如不存在执行的sql 语句 ,sqlForExits
假如存在执行的sql 语句。SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = db AND TABLE_NAME =tb AND COLUMN_NAME = col
mysql存在一个记录所有表信息的数据库information_schema ,查询这张表的列。PREPARE stmt FROM @sql;
预编译语句
EXECUTE stmt;
执行语句。
最后就可以使用整个存储过程了:
CALL PROC_TEMP_ALTER_COL_SAFE('test','user','test','ADD test VARCHAR (10) NULL','CHANGE test test datetime NULL');
修改test 数据库的user表的test字段,假如不存在就新增,假如存在这修改为正确格式。