1.0.509.sql 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. -- =====================================================================================
  2. -- 1.0.509 · S0 MASTER DATA PLATFORM · PHASE 2 · C3 关系桥(3 个)
  3. --
  4. -- EmpWorkDutyMaster → mdp_stg_s0_emp_work_duty → bridge_employee_work_duty
  5. -- LineSkillMaster → mdp_stg_s0_line_post → dim_line_post
  6. -- LineSkillDetail → mdp_stg_s0_line_post → bridge_line_post_skill (父子共用 staging)
  7. --
  8. -- 身份口径(沿用 D-025):tenant_id + 业务码;Domain/company/factory 均 LEGACY_SCOPE。
  9. -- 但**有一处例外经实测确立**:EmpWorkDuty 的 location_code **必须留在身份里** ——
  10. -- tenant+Employee+Duty 实测有 1 组重复(797…229 的 G00308 同一串 Duty 下
  11. -- Location=1001 与 1000 是两条不同职责、物料也不同)。库位是真实区分维,不是 legacy scope。
  12. --
  13. -- 🔴 LineSkillDetail 是本仓第 4 张 dual-column 表,且最危险:四对双列里三对是「有值但发散」型
  14. -- (影子列 250/261 非空,与真列**没有一行相等**)—— 取错不报错,得到看起来合法的错值。
  15. -- 尤其 bridge 的目标列 effective_date 其源物理列是 **StartDate**,
  16. -- 而源表另有一个字面叫 effective_date 的 0/261 影子列。已加契约测试钉死。
  17. --
  18. -- 🔴 父连接必须走自然键:代理键 LineSkillRecID 同租户孤儿 210/261、忽略租户后 175 行落到别的租户;
  19. -- PersonSkillId 更甚,250/261 属于别的租户。自然键 (tenant, ProdLine, JOBNo) 三租户全 0 孤儿。
  20. -- 两个 legacy id 仅作留痕列物化,任何 join 都不得使用。
  21. --
  22. -- EmpSkills **不在本批**:源侧 tenant+Employee+SkillNo 有 2 组重复(RecID 4848/4943 与 5156/4945),
  23. -- 需业务 owner 经 CRUD 删除接口清理后才能接入(见 KNOWN-ISSUES)。
  24. -- =====================================================================================
  25. -- ── 一、贴源表(2 张)──
  26. CREATE TABLE IF NOT EXISTS `mdp_stg_s0_emp_work_duty` (
  27. `id` bigint NOT NULL AUTO_INCREMENT,
  28. `tenant_id` bigint NOT NULL DEFAULT 0,
  29. `factory_id` bigint DEFAULT NULL,
  30. `source_system` varchar(50) NOT NULL DEFAULT 'AIDOPDEV_MYSQL',
  31. `source_table` varchar(100) NOT NULL,
  32. `source_row_id` varchar(100) NOT NULL,
  33. `source_biz_key` varchar(300) DEFAULT NULL,
  34. `sync_batch_id` varchar(100) NOT NULL,
  35. `sync_time` datetime NOT NULL,
  36. `process_status` varchar(20) NOT NULL DEFAULT 'PENDING',
  37. `raw_data` json NOT NULL,
  38. `process_message` varchar(500) DEFAULT NULL,
  39. `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  40. `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  41. PRIMARY KEY (`id`),
  42. UNIQUE KEY `uk_stg_s0_emp_work_duty` (`tenant_id`,`source_system`,`source_table`,`source_row_id`),
  43. KEY `idx_stg_s0_emp_work_duty_biz` (`source_biz_key`),
  44. KEY `idx_stg_s0_emp_work_duty_batch` (`tenant_id`,`sync_batch_id`)
  45. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='S0 贴源:员工物料职责(源 EmpWorkDutyMaster)';
  46. CREATE TABLE IF NOT EXISTS `mdp_stg_s0_line_post` (
  47. `id` bigint NOT NULL AUTO_INCREMENT,
  48. `tenant_id` bigint NOT NULL DEFAULT 0,
  49. `factory_id` bigint DEFAULT NULL,
  50. `source_system` varchar(50) NOT NULL DEFAULT 'AIDOPDEV_MYSQL',
  51. `source_table` varchar(100) NOT NULL,
  52. `source_row_id` varchar(100) NOT NULL,
  53. `source_biz_key` varchar(300) DEFAULT NULL,
  54. `sync_batch_id` varchar(100) NOT NULL,
  55. `sync_time` datetime NOT NULL,
  56. `process_status` varchar(20) NOT NULL DEFAULT 'PENDING',
  57. `raw_data` json NOT NULL,
  58. `process_message` varchar(500) DEFAULT NULL,
  59. `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  60. `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  61. PRIMARY KEY (`id`),
  62. UNIQUE KEY `uk_stg_s0_line_post` (`tenant_id`,`source_system`,`source_table`,`source_row_id`),
  63. KEY `idx_stg_s0_line_post_biz` (`source_biz_key`),
  64. KEY `idx_stg_s0_line_post_batch` (`tenant_id`,`sync_batch_id`)
  65. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='S0 贴源:产线岗位与岗位技能(LineSkillMaster + LineSkillDetail 共用,靠 source_table 隔离)';
  66. -- ── 二、桥接 / 维度表(3 张)──
  67. CREATE TABLE IF NOT EXISTS `bridge_employee_work_duty` (
  68. `id` bigint NOT NULL AUTO_INCREMENT,
  69. `tenant_id` bigint NOT NULL,
  70. `employee_code` varchar(100) NOT NULL COMMENT '工号(业务键)← $.Employee;按业务键引用 dim_employee',
  71. `duty` varchar(500) NOT NULL COMMENT '职责串(业务键)← $.Duty',
  72. `location_code` varchar(100) NOT NULL COMMENT '库位(**业务键,不可省**)← $.Location;实测同 Employee+Duty 下有两个不同 Location',
  73. `domain_code` varchar(50) NOT NULL COMMENT 'LEGACY_SCOPE ← $.Domain',
  74. `company_id` bigint NOT NULL COMMENT 'LEGACY_SCOPE ← $.company_ref_id',
  75. `factory_id` bigint NOT NULL COMMENT 'LEGACY_SCOPE ← $.factory_ref_id',
  76. `line_code` varchar(100) DEFAULT NULL COMMENT '← $.ProdLine;软引用 dim_line,无 FK',
  77. `item_num` varchar(100) DEFAULT NULL COMMENT '← $.ItemNum',
  78. `item_num_from` varchar(100) DEFAULT NULL COMMENT '← $.ItemNum1',
  79. `item_num_to` varchar(100) DEFAULT NULL COMMENT '← $.ItemNum2',
  80. `emp_type` varchar(50) DEFAULT NULL COMMENT '← $.EmpType',
  81. `source_system` varchar(50) NOT NULL,
  82. `source_biz_key` varchar(300) NOT NULL,
  83. `source_updated_at` datetime DEFAULT NULL COMMENT '← $.UpdateTime(源 10/25,允许 NULL)',
  84. `sync_batch_id` varchar(64) NOT NULL,
  85. `sync_time` datetime NOT NULL,
  86. `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  87. `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  88. PRIMARY KEY (`id`),
  89. -- 索引字节 = 8 + 100*4 + 500*4 + 100*4 = 2808 < 3072(DYNAMIC/utf8mb4)。任一列加宽都会越界,改前必须重算。
  90. UNIQUE KEY `uk_bridge_employee_work_duty` (`tenant_id`,`employee_code`,`duty`,`location_code`),
  91. KEY `idx_bridge_ewd_batch` (`sync_batch_id`),
  92. KEY `idx_bridge_ewd_emp` (`tenant_id`,`employee_code`)
  93. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='S0 关系桥:员工物料职责。源 EmpWorkDutyMaster,FULL REPLACE。父 = dim_employee。';
  94. CREATE TABLE IF NOT EXISTS `dim_line_post` (
  95. `id` bigint NOT NULL AUTO_INCREMENT,
  96. `tenant_id` bigint NOT NULL,
  97. `line_code` varchar(100) NOT NULL COMMENT '产线码(业务键)← $.ProdLine;软引用 dim_line,28/57 对不上故**不设父**',
  98. `job_no` varchar(100) NOT NULL COMMENT '岗位码(业务键)← $.JOBNo;当前每租户单值,保留以防不可逆键收缩',
  99. `domain_code` varchar(50) NOT NULL COMMENT 'LEGACY_SCOPE ← $.Domain',
  100. `job_name` varchar(255) DEFAULT NULL COMMENT '← $.JOBDescr',
  101. `site` varchar(12) DEFAULT NULL COMMENT '← $.Site(源 0/57 全 NULL);保留可见性——它在源 UK 里,丢了将来看不出身份为何被破坏',
  102. `order_by` int DEFAULT NULL COMMENT '← $.Orderby',
  103. `run_crew` decimal(10,3) DEFAULT NULL COMMENT '← $.RunCrew;**scale 必须与源 decimal(10,3) 逐位相同**,否则 CAST AS CHAR 后 0.000≠0.0,校验和 FAIL',
  104. `source_system` varchar(50) NOT NULL,
  105. `source_biz_key` varchar(300) NOT NULL,
  106. `source_updated_at` datetime DEFAULT NULL COMMENT '← $.UpdateTime',
  107. `sync_batch_id` varchar(64) NOT NULL,
  108. `sync_time` datetime NOT NULL,
  109. `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  110. `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  111. PRIMARY KEY (`id`),
  112. UNIQUE KEY `uk_dim_line_post` (`tenant_id`,`line_code`,`job_no`),
  113. KEY `idx_dim_line_post_batch` (`sync_batch_id`)
  114. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='S0 维度:产线岗位。源 LineSkillMaster。源侧 UK 含全 NULL 的 Site 故形同虚设,本表 UK 是第一道真守卫。';
  115. CREATE TABLE IF NOT EXISTS `bridge_line_post_skill` (
  116. `id` bigint NOT NULL AUTO_INCREMENT,
  117. `tenant_id` bigint NOT NULL,
  118. `line_code` varchar(100) NOT NULL COMMENT '业务键 + 父键 ← $.ProdLine',
  119. `job_no` varchar(100) NOT NULL COMMENT '业务键 + 父键 ← $.JOBNo',
  120. `skill_code` varchar(100) NOT NULL COMMENT '业务键 ← $.SkillNo;软引用 dim_person_skill(210/261 对不上,**不设父**)',
  121. `domain_code` varchar(50) DEFAULT NULL COMMENT 'LEGACY_SCOPE ← $.Domain(源可空,故不设 Required)',
  122. `site` varchar(12) DEFAULT NULL COMMENT '← $.Site(源 0/261)',
  123. `effective_date` datetime DEFAULT NULL COMMENT '🔴 源物理列是 **$.StartDate**,不是同表那个 0/261 的影子列 effective_date',
  124. `required_level` varchar(50) DEFAULT NULL COMMENT '← $.required_level',
  125. `remark` varchar(500) DEFAULT NULL COMMENT '← $.remark',
  126. `is_enabled` tinyint(1) NOT NULL COMMENT '← $.is_enabled',
  127. `legacy_line_skill_rec_id` bigint DEFAULT NULL COMMENT '⚠️ 仅留痕 ← $.LineSkillRecID;同租户孤儿 210/261,**禁止 join**',
  128. `legacy_person_skill_id` bigint DEFAULT NULL COMMENT '⚠️ 仅留痕 ← $.PersonSkillId;250/261 属于别的租户,**禁止 join**',
  129. `source_system` varchar(50) NOT NULL,
  130. `source_biz_key` varchar(300) NOT NULL,
  131. `source_updated_at` datetime DEFAULT NULL COMMENT '← $.UpdateTime',
  132. `sync_batch_id` varchar(64) NOT NULL,
  133. `sync_time` datetime NOT NULL,
  134. `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  135. `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  136. PRIMARY KEY (`id`),
  137. UNIQUE KEY `uk_bridge_line_post_skill` (`tenant_id`,`line_code`,`job_no`,`skill_code`),
  138. KEY `idx_bls_parent` (`tenant_id`,`line_code`,`job_no`),
  139. KEY `idx_bls_batch` (`sync_batch_id`)
  140. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='S0 关系桥:产线岗位技能。源 LineSkillDetail,FULL REPLACE。父 = dim_line_post,**走自然键**。';
  141. -- ── 三、mdp_entity 入站配置(3 条,全 FULL / incr_column=NULL)──
  142. SET @src_id = (SELECT `id` FROM `mdp_source` WHERE `source_code` = 'AIDOPDEV_MYSQL' LIMIT 1);
  143. INSERT INTO `mdp_entity`
  144. (`tenant_id`,`source_id`,`entity_code`,`entity_name`,`entity_type`,
  145. `source_table_name`,`target_table_name`,`sync_mode`,`incr_column`,`batch_size`,
  146. `biz_key_expr`,`status`,`create_time`,`update_time`)
  147. SELECT 0, @src_id, 'S0_EMP_WORK_DUTY', 'S0 员工物料职责入站', 'TABLE',
  148. 'EmpWorkDutyMaster', 'mdp_stg_s0_emp_work_duty', 'FULL', NULL, 5000,
  149. 'Employee,Duty,Location', 1, NOW(), NOW()
  150. WHERE @src_id IS NOT NULL
  151. AND NOT EXISTS (SELECT 1 FROM `mdp_entity` WHERE `entity_code` = 'S0_EMP_WORK_DUTY');
  152. INSERT INTO `mdp_entity`
  153. (`tenant_id`,`source_id`,`entity_code`,`entity_name`,`entity_type`,
  154. `source_table_name`,`target_table_name`,`sync_mode`,`incr_column`,`batch_size`,
  155. `biz_key_expr`,`status`,`create_time`,`update_time`)
  156. SELECT 0, @src_id, 'S0_LINE_POST', 'S0 产线岗位入站', 'TABLE',
  157. 'LineSkillMaster', 'mdp_stg_s0_line_post', 'FULL', NULL, 5000,
  158. 'ProdLine,JOBNo', 1, NOW(), NOW()
  159. WHERE @src_id IS NOT NULL
  160. AND NOT EXISTS (SELECT 1 FROM `mdp_entity` WHERE `entity_code` = 'S0_LINE_POST');
  161. INSERT INTO `mdp_entity`
  162. (`tenant_id`,`source_id`,`entity_code`,`entity_name`,`entity_type`,
  163. `source_table_name`,`target_table_name`,`sync_mode`,`incr_column`,`batch_size`,
  164. `biz_key_expr`,`status`,`create_time`,`update_time`)
  165. SELECT 0, @src_id, 'S0_LINE_POST_SKILL', 'S0 产线岗位技能入站', 'TABLE',
  166. 'LineSkillDetail', 'mdp_stg_s0_line_post', 'FULL', NULL, 5000,
  167. 'ProdLine,JOBNo,SkillNo', 1, NOW(), NOW()
  168. WHERE @src_id IS NOT NULL
  169. AND NOT EXISTS (SELECT 1 FROM `mdp_entity` WHERE `entity_code` = 'S0_LINE_POST_SKILL');
  170. -- ── 回滚(注释,非可执行)──
  171. -- DROP TABLE IF EXISTS `bridge_line_post_skill`,`dim_line_post`,`bridge_employee_work_duty`;
  172. -- DROP TABLE IF EXISTS `mdp_stg_s0_line_post`,`mdp_stg_s0_emp_work_duty`;
  173. -- DELETE FROM `mdp_entity` WHERE `tenant_id`=0 AND `entity_code` IN
  174. -- ('S0_EMP_WORK_DUTY','S0_LINE_POST','S0_LINE_POST_SKILL');