fix: 修复迁移脚本被 .gitignore 忽略的问题
- 添加 !**/db/migration/*.sql 例外规则 - 补充 V32-V37 Flyway 迁移脚本 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
640fbc94f9
commit
10936b7a78
3
.gitignore
vendored
3
.gitignore
vendored
@ -12,6 +12,9 @@ backups/
|
|||||||
*.sql
|
*.sql
|
||||||
*.db
|
*.db
|
||||||
|
|
||||||
|
# === 例外:Flyway 迁移脚本必须提交 ===
|
||||||
|
!**/db/migration/*.sql
|
||||||
|
|
||||||
# === IDE 和编辑器 ===
|
# === IDE 和编辑器 ===
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
|
|||||||
@ -0,0 +1,95 @@
|
|||||||
|
-- =====================================================
|
||||||
|
-- 迁移 V32: 修复 V31 迁移问题并完成三层结构修复
|
||||||
|
--
|
||||||
|
-- 这个迁移脚本会:
|
||||||
|
-- 1. 检查并修复可能存在的部分数据
|
||||||
|
-- 2. 使用 INSERT IGNORE 避免重复键错误
|
||||||
|
-- 3. 完成三层课程结构的修复
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 临时禁用外键约束
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第一步:清理可能存在的错误数据
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 删除自引用的 course_collection_package 关联
|
||||||
|
DELETE FROM `course_collection_package` WHERE `collection_id` = `package_id`;
|
||||||
|
|
||||||
|
-- 删除错误的 course_collection 数据(ID 3, 4, 5)
|
||||||
|
DELETE FROM `course_collection` WHERE `id` IN (3, 4, 5);
|
||||||
|
|
||||||
|
-- 清理 tenant_package 中的 collection_id 引用
|
||||||
|
UPDATE `tenant_package` SET `collection_id` = NULL WHERE `collection_id` IN (3, 4, 5);
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第二步:创建课程套餐数据(使用 INSERT IGNORE)
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `course_collection` (`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `package_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`) VALUES
|
||||||
|
(100, '完整阅读能力培养课程体系', '涵盖小班至学前班的完整阅读能力培养体系,包含语言启蒙、艺术创作、科学探索等多个领域的课程包', 29999, 24999, 'FIXED', '["小班", "中班", "大班", "学前班"]', 3, 'PUBLISHED', NOW(), 1, NOW(), 1, '审核通过', NOW(), 'system', NOW(), 'system', NOW(), 0);
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第三步:创建课程包数据(使用 INSERT IGNORE)
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `course_package` (`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `course_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`) VALUES
|
||||||
|
(101, '语言启蒙课程包', '通过绘本阅读培养幼儿的语言表达能力和阅读兴趣', 9999, 7999, 'FIXED', '["小班", "中班"]', 3, 'PUBLISHED', NOW(), 1, NOW(), 1, '审核通过', NOW(), 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(102, '艺术创作课程包', '通过艺术活动培养幼儿的审美能力和创造力', 9999, 7999, 'FIXED', '["小班", "中班", "大班"]', 3, 'PUBLISHED', NOW(), 1, NOW(), 1, '审核通过', NOW(), 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(103, '科学探索课程包', '通过科学活动培养幼儿的探究精神和逻辑思维', 9999, 7999, 'FIXED', '["中班", "大班", "学前班"]', 4, 'PUBLISHED', NOW(), 1, NOW(), 1, '审核通过', NOW(), 'system', NOW(), 'system', NOW(), 0);
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第四步:创建关联数据(使用 INSERT IGNORE)
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `course_collection_package` (`id`, `collection_id`, `package_id`, `sort_order`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`) VALUES
|
||||||
|
(101, 100, 101, 1, 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(102, 100, 102, 2, 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(103, 100, 103, 3, 'system', NOW(), 'system', NOW(), 0);
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第五步:创建课程数据(使用 INSERT IGNORE)
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `course` (`id`, `tenant_id`, `name`, `category`, `description`, `cover_url`, `age_range`, `difficulty_level`, `duration_minutes`, `status`, `is_system`, `core_content`, `objectives`, `schedule_ref_data`, `created_at`, `updated_at`, `deleted`) VALUES
|
||||||
|
(101, NULL, '小猪佩奇绘本阅读导入课', '语言艺术', '通过小猪佩奇绘本导入阅读主题,激发幼儿兴趣', '/courses/peppa-intro/cover.jpg', '3-6 岁', 'BEGINNER', 20, 'PUBLISHED', 1, '语言导入课程', '激发阅读兴趣', '[{"lessonType":"导入课","recommendation":"每学期开学第一周进行,作为整个阅读体系的导入课程。建议1-2课时完成。","sessions":2}]', NOW(), NOW(), 0),
|
||||||
|
(102, NULL, '小猪佩奇集体阅读课', '语言艺术', '集体阅读小猪佩奇绘本,培养集体阅读习惯', '/courses/peppa-collective/cover.jpg', '3-6 岁', 'BEGINNER', 30, 'PUBLISHED', 1, '语言集体课程', '培养集体阅读能力', '[{"lessonType":"集体课","recommendation":"每月进行2次,建议安排在周五上午。每次30-35分钟,包含共读、讨论、表演环节。","sessions":8,"frequency":"每月2次"}]', NOW(), NOW(), 0),
|
||||||
|
(103, NULL, '语言领域课程-小猪佩奇', '语言艺术', '深入学习语言领域的知识点和能力', '/courses/peppa-language/cover.jpg', '3-6 岁', 'BEGINNER', 25, 'PUBLISHED', 1, '五大领域语言课程', '提升语言表达能力', '[{"lessonType":"五大领域语言课","recommendation":"每周2次,建议安排在周二和周四。每次25分钟,重点培养听说能力。","sessions":16,"frequency":"每周2次"}]', NOW(), NOW(), 0),
|
||||||
|
(104, NULL, '彩虹色的花导入课', '艺术创作', '导入艺术创作主题', '/courses/rainbow-intro/cover.jpg', '3-5 岁', 'BEGINNER', 20, 'PUBLISHED', 1, '艺术导入课程', '激发艺术兴趣', '[{"lessonType":"导入课","recommendation":"每学期开学第一周进行","sessions":1}]', NOW(), NOW(), 0),
|
||||||
|
(105, NULL, '彩虹色的花集体创作课', '艺术创作', '集体进行艺术创作', '/courses/rainbow-collective/cover.jpg', '3-5 岁', 'BEGINNER', 35, 'PUBLISHED', 1, '艺术集体课程', '培养集体创作能力', '[{"lessonType":"集体课","recommendation":"每月1次,建议安排在周三下午","sessions":4}]', NOW(), NOW(), 0),
|
||||||
|
(106, NULL, '艺术领域课程-彩虹色的花', '艺术创作', '五大领域艺术课程', '/courses/rainbow-art/cover.jpg', '3-5 岁', 'BEGINNER', 30, 'PUBLISHED', 1, '五大领域艺术课程', '提升艺术表现能力', '[{"lessonType":"五大领域艺术课","recommendation":"每周1次,建议安排在周一上午","sessions":8}]', NOW(), NOW(), 0),
|
||||||
|
(107, NULL, '牙齿大街的新鲜事导入课', '科学探索', '导入科学探索主题', '/courses/teeth-intro/cover.jpg', '4-6 岁', 'INTERMEDIATE', 20, 'PUBLISHED', 1, '科学导入课程', '激发科学探索兴趣', '[{"lessonType":"导入课","recommendation":"每学期开学第一周进行","sessions":1}]', NOW(), NOW(), 0),
|
||||||
|
(108, NULL, '牙齿大街集体探究课', '科学探索', '集体进行科学探究', '/courses/teeth-collective/cover.jpg', '4-6 岁', 'INTERMEDIATE', 35, 'PUBLISHED', 1, '科学集体课程', '培养集体探究能力', '[{"lessonType":"集体课","recommendation":"每月1次,建议安排在周二下午","sessions":4}]', NOW(), NOW(), 0),
|
||||||
|
(109, NULL, '健康领域课程-牙齿大街', '科学探索', '五大领域健康课程', '/courses/teeth-health/cover.jpg', '4-6 岁', 'INTERMEDIATE', 30, 'PUBLISHED', 1, '五大领域健康课程', '培养健康意识', '[{"lessonType":"五大领域健康课","recommendation":"每周1次,建议安排在周三上午","sessions":8}]', NOW(), NOW(), 0),
|
||||||
|
(110, NULL, '科学领域课程-牙齿大街', '科学探索', '五大领域科学课程', '/courses/teeth-science/cover.jpg', '4-6 岁', 'INTERMEDIATE', 30, 'PUBLISHED', 1, '五大领域科学课程', '培养科学探究能力', '[{"lessonType":"五大领域科学课","recommendation":"每周1次,建议安排在周五上午","sessions":8}]', NOW(), NOW(), 0);
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第六步:创建课程包与课程的关联(使用 INSERT IGNORE)
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `course_package_course` (`id`, `package_id`, `course_id`, `grade_level`, `sort_order`) VALUES
|
||||||
|
(1001, 101, 101, '小班', 1),
|
||||||
|
(1002, 101, 102, '小班', 2),
|
||||||
|
(1003, 101, 103, '小班', 3),
|
||||||
|
(1004, 102, 104, '小班', 1),
|
||||||
|
(1005, 102, 105, '小班', 2),
|
||||||
|
(1006, 102, 106, '小班', 3),
|
||||||
|
(1007, 103, 107, '中班', 1),
|
||||||
|
(1008, 103, 108, '中班', 2),
|
||||||
|
(1009, 103, 109, '中班', 3),
|
||||||
|
(1010, 103, 110, '中班', 4);
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第七步:更新租户套餐关联
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 将租户的套餐关联更新到新的课程套餐(collection_id = 100)
|
||||||
|
UPDATE `tenant_package` SET `collection_id` = 100 WHERE `id` IN (1, 2);
|
||||||
|
|
||||||
|
-- 重新启用外键约束
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- V32 迁移完成
|
||||||
|
-- =====================================================
|
||||||
@ -0,0 +1,125 @@
|
|||||||
|
-- =====================================================
|
||||||
|
-- 迁移 V33: 将8个课程包转换为8个套餐
|
||||||
|
--
|
||||||
|
-- 这个迁移会:
|
||||||
|
-- 1. 为8个现有课程包创建对应的8个套餐
|
||||||
|
-- 2. 将每个课程包关联到其对应的套餐
|
||||||
|
-- 3. 更新所有关联关系
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第一步:创建8个套餐(使用新ID避免冲突)
|
||||||
|
-- 课程包ID: 3, 4, 5, 6, 7, 101, 102, 103
|
||||||
|
-- 新套餐ID: 203, 204, 205, 206, 207, 208, 209, 210
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
INSERT INTO `course_collection`
|
||||||
|
(`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `package_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
SELECT
|
||||||
|
203, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, 1, `status`,
|
||||||
|
`submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`,
|
||||||
|
`create_by`, `created_at`, `update_by`, `updated_at`, 0
|
||||||
|
FROM `course_package` WHERE `id` = 3;
|
||||||
|
|
||||||
|
INSERT INTO `course_collection`
|
||||||
|
(`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `package_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
SELECT
|
||||||
|
204, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, 1, `status`,
|
||||||
|
`submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`,
|
||||||
|
`create_by`, `created_at`, `update_by`, `updated_at`, 0
|
||||||
|
FROM `course_package` WHERE `id` = 4;
|
||||||
|
|
||||||
|
INSERT INTO `course_collection`
|
||||||
|
(`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `package_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
SELECT
|
||||||
|
205, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, 1, `status`,
|
||||||
|
`submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`,
|
||||||
|
`create_by`, `created_at`, `update_by`, `updated_at`, 0
|
||||||
|
FROM `course_package` WHERE `id` = 5;
|
||||||
|
|
||||||
|
INSERT INTO `course_collection`
|
||||||
|
(`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `package_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
SELECT
|
||||||
|
206, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, 1, `status`,
|
||||||
|
`submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`,
|
||||||
|
`create_by`, `created_at`, `update_by`, `updated_at`, 0
|
||||||
|
FROM `course_package` WHERE `id` = 6;
|
||||||
|
|
||||||
|
INSERT INTO `course_collection`
|
||||||
|
(`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `package_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
SELECT
|
||||||
|
207, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, 1, `status`,
|
||||||
|
`submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`,
|
||||||
|
`create_by`, `created_at`, `update_by`, `updated_at`, 0
|
||||||
|
FROM `course_package` WHERE `id` = 7;
|
||||||
|
|
||||||
|
INSERT INTO `course_collection`
|
||||||
|
(`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `package_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
SELECT
|
||||||
|
208, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, 1, `status`,
|
||||||
|
`submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`,
|
||||||
|
`create_by`, `created_at`, `update_by`, `updated_at`, 0
|
||||||
|
FROM `course_package` WHERE `id` = 101;
|
||||||
|
|
||||||
|
INSERT INTO `course_collection`
|
||||||
|
(`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `package_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
SELECT
|
||||||
|
209, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, 1, `status`,
|
||||||
|
`submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`,
|
||||||
|
`create_by`, `created_at`, `update_by`, `updated_at`, 0
|
||||||
|
FROM `course_package` WHERE `id` = 102;
|
||||||
|
|
||||||
|
INSERT INTO `course_collection`
|
||||||
|
(`id`, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, `package_count`, `status`, `submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
SELECT
|
||||||
|
210, `name`, `description`, `price`, `discount_price`, `discount_type`, `grade_levels`, 1, `status`,
|
||||||
|
`submitted_at`, `submitted_by`, `reviewed_at`, `reviewed_by`, `review_comment`, `published_at`,
|
||||||
|
`create_by`, `created_at`, `update_by`, `updated_at`, 0
|
||||||
|
FROM `course_package` WHERE `id` = 103;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第二步:建立套餐与课程包的关联
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
INSERT INTO `course_collection_package`
|
||||||
|
(`id`, `collection_id`, `package_id`, `sort_order`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
VALUES
|
||||||
|
(1001, 203, 3, 1, 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(1002, 204, 4, 1, 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(1003, 205, 5, 1, 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(1004, 206, 6, 1, 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(1005, 207, 7, 1, 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(1006, 208, 101, 1, 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(1007, 209, 102, 1, 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(1008, 210, 103, 1, 'system', NOW(), 'system', NOW(), 0);
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第三步:更新租户套餐关联
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 删除原有的套餐关联
|
||||||
|
DELETE FROM `tenant_package`;
|
||||||
|
|
||||||
|
-- 重新创建套餐关联,关联到新的8个套餐
|
||||||
|
-- 注意:需要同时提供 package_id 和 collection_id
|
||||||
|
INSERT INTO `tenant_package` (`id`, `tenant_id`, `package_id`, `collection_id`, `start_date`, `end_date`, `status`, `create_by`, `created_at`, `update_by`, `updated_at`, `deleted`)
|
||||||
|
VALUES
|
||||||
|
(1, 1, 3, 203, CURDATE(), DATE_ADD(CURDATE(), INTERVAL 1 YEAR), 'ACTIVE', 'system', NOW(), 'system', NOW(), 0),
|
||||||
|
(2, 1, 4, 204, CURDATE(), DATE_ADD(CURDATE(), INTERVAL 1 YEAR), 'ACTIVE', 'system', NOW(), 'system', NOW(), 0);
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第四步:清理旧的套餐数据
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 删除旧的套餐(ID 100)
|
||||||
|
DELETE FROM `course_collection_package` WHERE `collection_id` = 100;
|
||||||
|
DELETE FROM `course_collection` WHERE `id` = 100;
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- V33 迁移完成
|
||||||
|
-- 现在有8个套餐,每个套餐包含1个原有的课程包
|
||||||
|
-- =====================================================
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
-- =====================================================
|
||||||
|
-- 迁移 V34: 清理旧的套餐数据
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- 删除旧的套餐(ID 100)
|
||||||
|
DELETE FROM `course_collection_package` WHERE `collection_id` = 100;
|
||||||
|
DELETE FROM `course_collection` WHERE `id` = 100;
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- V34 迁移完成
|
||||||
|
-- =====================================================
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
-- =====================================================
|
||||||
|
-- 迁移 V35: 清理混淆的旧表结构
|
||||||
|
--
|
||||||
|
-- 清理旧的 course_package 表,统一使用 course 表作为课程包表
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第一步:检查并备份要删除的数据
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 检查 course_package 表中是否有真实课程包数据
|
||||||
|
-- (即有 course_lesson 数据的)
|
||||||
|
SELECT
|
||||||
|
'=== 检查 course_package 表中需要迁移的数据 ===' as info;
|
||||||
|
|
||||||
|
-- 如果有需要保留的数据,可以先备份
|
||||||
|
CREATE TABLE IF NOT EXISTS course_package_backup AS
|
||||||
|
SELECT * FROM course_package WHERE 1=0;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第二步:删除旧的关联表
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
'=== 删除旧的关联表 ===' as info;
|
||||||
|
|
||||||
|
-- 删除课程包与课程的关联表(旧的关联方式)
|
||||||
|
DROP TABLE IF EXISTS course_package_course;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第三步:删除旧的课程包表
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
'=== 删除旧的 course_package 表 ===' as info;
|
||||||
|
|
||||||
|
-- 注意:V33迁移中course_package的数据已经转换为8个套餐了
|
||||||
|
-- 所以现在可以安全删除这个表
|
||||||
|
DROP TABLE IF EXISTS course_package;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第四步:验证关联关系
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
'=== 验证 course_collection_package 关联 ===' as info;
|
||||||
|
|
||||||
|
-- 检查套餐与课程包的关联是否正确
|
||||||
|
-- 现在应该关联到 course 表(不是 course_package 表)
|
||||||
|
SELECT
|
||||||
|
cc.id as collection_id,
|
||||||
|
cc.name as collection_name,
|
||||||
|
ccp.package_id,
|
||||||
|
c.name as package_name,
|
||||||
|
c.schedule_ref_data
|
||||||
|
FROM course_collection cc
|
||||||
|
LEFT JOIN course_collection_package ccp ON ccp.collection_id = cc.id
|
||||||
|
LEFT JOIN course c ON c.id = ccp.package_id
|
||||||
|
ORDER BY cc.id, ccp.sort_order;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
'=== V35 迁移完成 ===' as info;
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
-- =====================================================
|
||||||
|
-- 迁移 V36: 重命名 course 表为 course_package
|
||||||
|
--
|
||||||
|
-- 统一命名:course → course_package(课程包表)
|
||||||
|
-- 同时更新所有外键关联
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第一步:重命名主表(幂等操作)
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SELECT '=== 检查并重命名 course 表为 course_package ===' as info;
|
||||||
|
|
||||||
|
-- 只有当 course 表存在时才重命名
|
||||||
|
-- 如果 course_package 表已存在,则跳过重命名
|
||||||
|
SET @table_exists = (SELECT COUNT(*) FROM information_schema.tables
|
||||||
|
WHERE table_schema = DATABASE() AND table_name = 'course');
|
||||||
|
|
||||||
|
SET @target_exists = (SELECT COUNT(*) FROM information_schema.tables
|
||||||
|
WHERE table_schema = DATABASE() AND table_name = 'course_package');
|
||||||
|
|
||||||
|
-- 如果 course 表存在且 course_package 不存在,则重命名
|
||||||
|
-- 使用预处理语句实现条件逻辑
|
||||||
|
SET @rename_sql = IF(@table_exists > 0 AND @target_exists = 0,
|
||||||
|
'RENAME TABLE course TO course_package',
|
||||||
|
'SELECT ''course_table already renamed or does not exist'' as info');
|
||||||
|
|
||||||
|
PREPARE stmt FROM @rename_sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第二步:更新关联表的外键
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SELECT '=== 更新 course_lesson 表外键 ===' as info;
|
||||||
|
|
||||||
|
-- 删除旧的外键(如果存在)
|
||||||
|
-- MySQL 不支持 DROP FOREIGN KEY IF EXISTS,需要先检查是否存在
|
||||||
|
SET @fk_exists = (SELECT COUNT(*) FROM information_schema.key_column_usage
|
||||||
|
WHERE table_schema = DATABASE()
|
||||||
|
AND table_name = 'course_lesson'
|
||||||
|
AND constraint_name = 'fk_course_lesson_course_id');
|
||||||
|
|
||||||
|
SET @drop_fk_sql = IF(@fk_exists > 0,
|
||||||
|
'ALTER TABLE course_lesson DROP FOREIGN KEY fk_course_lesson_course_id',
|
||||||
|
'SELECT ''foreign key does not exist'' as info');
|
||||||
|
|
||||||
|
PREPARE stmt FROM @drop_fk_sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- 添加新的外键约束(指向 course_package)
|
||||||
|
-- 首先检查新约束是否已存在
|
||||||
|
SET @new_fk_exists = (SELECT COUNT(*) FROM information_schema.key_column_usage
|
||||||
|
WHERE table_schema = DATABASE()
|
||||||
|
AND table_name = 'course_lesson'
|
||||||
|
AND constraint_name = 'fk_course_lesson_package_id');
|
||||||
|
|
||||||
|
SET @add_fk_sql = IF(@new_fk_exists = 0,
|
||||||
|
'ALTER TABLE course_lesson ADD CONSTRAINT fk_course_lesson_package_id FOREIGN KEY (course_id) REFERENCES course_package(id) ON DELETE CASCADE',
|
||||||
|
'SELECT ''new foreign key already exists'' as info');
|
||||||
|
|
||||||
|
PREPARE stmt FROM @add_fk_sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 第三步:验证表结构
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SELECT '=== 验证重命名后的表结构 ===' as info;
|
||||||
|
|
||||||
|
SHOW TABLES LIKE 'course_package';
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 完成
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
SELECT '=== V36 迁移完成 ===' as info;
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
-- =====================================================
|
||||||
|
-- 迁移 V37: 修复失败的 V36 迁移
|
||||||
|
--
|
||||||
|
-- 此迁移删除失败的 V36 记录,让 V36 可以重新运行
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 删除失败的 V36 迁移记录
|
||||||
|
DELETE FROM flyway_schema_history
|
||||||
|
WHERE version = '36' AND success = 0;
|
||||||
|
|
||||||
|
-- 验证删除
|
||||||
|
SELECT '=== 已删除失败的 V36 迁移记录 ===' as info;
|
||||||
|
SELECT version, description, success, installed_on
|
||||||
|
FROM flyway_schema_history
|
||||||
|
WHERE version = '36'
|
||||||
|
ORDER BY installed_rank DESC;
|
||||||
Loading…
Reference in New Issue
Block a user