咱们在进行新的功能开发时,因为历史项目的存在,须要在程序起动时对数据进行判断,若是发现是历史版本的数据,则须要对数据进行一些特定的处理;若是是最新的数据,则跳过处理过程。这在系统的版本迭代中尤其重要!本文将阐述如何自动化的实现该过程。php
在数据库measurement
中,当存在数据表web_app_menu
,且该表中不存在db_type
字段时,为其添加db_type
字段。同时,进行部分数据的更新及删除操做。html
IF ELSE
控制流因此没法使用普通的SQL语句来实现以下的伪代码:mysql
if (存在('web_app_menu')) if (存在('db_type')) // 执行语句
解决方法:使用存储过程来实如今MYSQL中的逻辑判断,进行实现伪代码中的逻辑功能。web
;
则会当即执行;
前面的语句。存储过程在使用前,须要先进行定义,在定义的过程当中,咱们须要加入SQL语句,这就避免不了,咱们在SQL语句中出现;
。而一旦;
出现,mysql会当即执行;
之前语句,此时,因为咱们的存储过程未定义完毕,因此会获得一个“语法错误”的提示。spring
解决方法: 在定义存储过程前,重写;
。以使得在定义存储时,即便出现了;
,也不被mysql执行。在定义结束后,再将重写的;
复原。sql
开始使用存储时,可能会遇到一个误区:储存定义后,为何没有自动执行。其实MYSQL中的存储过程,就像咱们在普通的语言中定义一个函数是同样的道理。函数定义后,并不会自动执行,只有当函数被调用时,才会被自动执行。因此,解决的方法也很简单:调用存储过程。数据库
-- 将 ; 转义为 // (即遇到//才至关于;) 防止定义 存储过程 时中,遇到 ; 而中断的问题。 DELIMITER // -- 若是存在存储过程(sql函数)FUN20180516则将其删除 DROP PROCEDURE IF EXISTS `FUN20180516` // -- 新建存储过程(sql函数),起名为:FUN20180518。至关于C中的(void FUN20180516()) CREATE PROCEDURE `FUN20180516` () -- 定义函数开始(至关于C中的 { ) BEGIN -- 声明变量 int hasDb DECLARE hasDb INT; DECLARE hasDbType INT; -- 执行语句(查询数据表是否存在),并将返回值给hasDb SELECT count(*) INTO hasDb FROM information_schema.tables WHERE (table_schema = 'measurement') AND (table_name= 'web_app_menu'); -- 若是数据表存在(注意:用=来判断,而不是==) IF hasDb = 1 THEN -- 判断字段是否存在 SELECT count(*) INTO hasDbType FROM information_schema.columns WHERE (table_schema = 'measurement') and (table_name= 'web_app_menu') and (column_name = 'db_type'); -- 字段不存在,则执行如下代码 IF hasDbType = 0 THEN ALTER TABLE `web_app_menu` ADD `db_type` VARCHAR(31) NOT NULL; UPDATE `web_app_menu` SET `db_type` = 'web_app_menu' WHERE db_type = ''; DELETE wr.* FROM web_app_menu_role wr WHERE wr.web_app_menu_id IN (SELECT w.id FROM web_app_menu w WHERE w.id IN (select w1.p_id FROM web_app_menu w1 WHERE w.route_name = 'measurementStandardAssessmentApply')); DELETE wr.* FROM web_app_menu_role wr WHERE wr.web_app_menu_id IN (SELECT w.id FROM web_app_menu w WHERE w.route_name = 'measurementStandardAssessmentApply'); DELETE w.* FROM web_app_menu w WHERE w.p_id IN (SELECT id FROM (SELECT id FROM web_app_menu w2 WHERE w2.route_name = 'measurementStandardAssessmentApply') x); DELETE w.* FROM web_app_menu w WHERE w.route_name = 'measurementStandardAssessmentApply'; -- 控制台打印日志 SELECT '20180516 success'; end if; END IF; -- 下面咱们用 // 至关于 END ;也就是说,咱们的函数定义完了,你能够一并进行加载了。 END // -- 再将 ; 恢复为 ;。防止后面的语句中,使用; 而不生效的问题 DELIMITER ; -- 调用函数 call FUN20180516();
首先: spring
支持两种方式在启动时执行SQL语句。其中是在resources
中创建data.sql
,另外一种是创建schema.sql
。两个文件的区别在于:data.sql
后于JPA执行,而schema.sql
先于JPA执行。
因为咱们须要在JPA起做用前先改变数据表的结构,删除冗余数据,因此须要创建schema.sql
。app
其次:spring并不支持DELIMITER
语法,因此在schema.sql
中,删除DELIMITER //
及DELIMITER
;。但一样的,若是不重写;
,则还会出现遇到;
则执行的问题。因此咱们还须要在配置文件中加入:spring.datasource.separator=//
来起到重写;
的做用。函数
此时,schema.sql
的形式以下:注意几处//spring-boot
-- spring.datasource.separator=//已通过;进行了改写 -- 若是存在存储过程(sql函数)FUN20180516则将其删除 DROP PROCEDURE IF EXISTS `FUN20180516` // -- 新建存储过程(sql函数),起名为:FUN20180518。至关于C中的(void FUN20180516()) CREATE PROCEDURE `FUN20180516` () -- 定义函数开始(至关于C中的 { ) BEGIN -- 声明变量 int hasDb DECLARE hasDb INT; DECLARE hasDbType INT; -- 执行语句(查询数据表是否存在),并将返回值给hasDb SELECT count(*) INTO hasDb FROM information_schema.tables WHERE (table_schema = 'measurement') and (table_schema = 'measurement') AND (table_name= 'web_app_menu'); -- 若是数据表存在(注意:用=来判断,而不是==) IF hasDb = 1 THEN -- 判断字段是否存在 SELECT count(*) INTO hasDbType FROM information_schema.columns WHERE (table_name= 'web_app_menu') and (column_name = 'db_type'); -- 字段不存在,则执行如下代码 IF hasDbType = 0 THEN ALTER TABLE `web_app_menu` ADD `db_type` VARCHAR(31) NOT NULL; UPDATE `web_app_menu` SET `db_type` = 'web_app_menu' WHERE db_type = ''; DELETE wr.* FROM web_app_menu_role wr WHERE wr.web_app_menu_id IN (SELECT w.id FROM web_app_menu w WHERE w.id IN (select w1.p_id FROM web_app_menu w1 WHERE w.route_name = 'measurementStandardAssessmentApply')); DELETE wr.* FROM web_app_menu_role wr WHERE wr.web_app_menu_id IN (SELECT w.id FROM web_app_menu w WHERE w.route_name = 'measurementStandardAssessmentApply'); DELETE w.* FROM web_app_menu w WHERE w.p_id IN (SELECT id FROM (SELECT id FROM web_app_menu w2 WHERE w2.route_name = 'measurementStandardAssessmentApply') x); DELETE w.* FROM web_app_menu w WHERE w.route_name = 'measurementStandardAssessmentApply'; -- 控制台打印日志 SELECT '20180516 success'; end if; END IF; END // -- 调用函数 call FUN20180516() //
application.properties
spring.datasource.separator=//
http://www.cnblogs.com/geaozh...
http://blog.sina.com.cn/s/blo...
https://www.techonthenet.com/...
https://dba.stackexchange.com...
https://docs.spring.io/spring...
https://stackoverflow.com/que...