-- ============================================================================= -- 联系人正式库统一:正式客户/供应商联系人通用表 yz_backend_contact_company -- -- 目标: -- 1. 正式客户/供应商联系人统一到 `yz_backend_contact_company` -- (backend 端「公司联系人」通用表,命名与 yz_backend_contact 保持一致); -- 2. 兼容历史表名 `yz_backend_erp_company_contact`: -- - 若新表不存在、旧表存在,直接 RENAME(结构与数据 100% 保留); -- - 若两表并存,则去重合并进新表,旧表改名为 *_bak 备份保留; -- 3. 迁移历史死表 `yz_tenant_crm_contact`(若存在且有数据):去重并入新表, -- 原表改名为 `yz_tenant_crm_contact_bak` 保留; -- 4. 线索/商机联系人仍然只存过程库 `yz_backend_crm_entity_contact`(本脚本不动)。 -- -- 去重键(判定为同一联系人):tenant_id + company_type + company_id + name + mobiles -- 说明: -- - 脚本幂等,可重复执行; -- - 任何迁移都是「先备份原表 / 或直接改名」再按去重键补插,绝不删除数据; -- - 执行本脚本的同时需要部署新版后端(模型表名已指向 yz_backend_contact_company)。 -- ============================================================================= SET NAMES utf8mb4; -- 记录初始状态 SET @has_new := ( SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'yz_backend_contact_company' ); SET @has_old_company := ( SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'yz_backend_erp_company_contact' ); -- ----------------------------------------------------------------------------- -- 1. 新表不存在、旧表存在 → 直接改名(保留全部结构、索引、自增、数据) -- ----------------------------------------------------------------------------- SET @sql := IF(@has_new = 0 AND @has_old_company > 0, 'RENAME TABLE `yz_backend_erp_company_contact` TO `yz_backend_contact_company`', 'SELECT ''step1: 跳过直接改名'' AS note'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 重新计算状态 SET @has_new := ( SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'yz_backend_contact_company' ); SET @has_old_company := ( SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'yz_backend_erp_company_contact' ); -- ----------------------------------------------------------------------------- -- 2. 确保正式表存在(新表也不存在、旧表也不存在时创建) -- ----------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `yz_backend_contact_company` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键ID', `tenant_id` varchar(64) NOT NULL DEFAULT '' COMMENT '租户ID', `company_type` varchar(20) NOT NULL DEFAULT '' COMMENT '公司类型:customer=客户,supplier=供应商', `company_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '公司ID(客户/供应商ID)', `name` varchar(50) NOT NULL DEFAULT '' COMMENT '联系人姓名', `gender` tinyint(4) NOT NULL DEFAULT 0 COMMENT '性别:0-未知 1-男 2-女', `phone` varchar(20) NOT NULL DEFAULT '' COMMENT '座机', `mobiles` text COMMENT '手机号,JSON数组,最多5个', `wechat` varchar(50) NOT NULL DEFAULT '' COMMENT '微信', `qq` varchar(50) NOT NULL DEFAULT '' COMMENT 'QQ', `dingtalk` varchar(50) NOT NULL DEFAULT '' COMMENT '钉钉', `email` varchar(100) NOT NULL DEFAULT '' COMMENT '邮箱', `department` varchar(50) NOT NULL DEFAULT '' COMMENT '部门', `position` varchar(50) NOT NULL DEFAULT '' COMMENT '职位', `home_address` varchar(255) NOT NULL DEFAULT '' COMMENT '家庭住址', `is_primary` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否主联系人:0-否 1-是', `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '状态:0-离职 1-在职', `remark` text COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `delete_time` datetime DEFAULT NULL COMMENT '删除时间(软删除)', PRIMARY KEY (`id`), KEY `idx_tenant_company` (`tenant_id`,`company_type`,`company_id`) COMMENT '按公司查询联系人', KEY `idx_name` (`tenant_id`,`name`) COMMENT '按姓名查询', KEY `idx_delete_time` (`delete_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='正式客户/供应商联系人通用表(backend 公司联系人)'; -- ----------------------------------------------------------------------------- -- 3. 两表并存时:旧表 yz_backend_erp_company_contact 去重并入新表,再改名备份 -- ----------------------------------------------------------------------------- SET @sql := IF(@has_old_company > 0, 'INSERT INTO `yz_backend_contact_company` (`tenant_id`,`company_type`,`company_id`,`name`,`gender`,`phone`,`mobiles`,`wechat`,`qq`,`dingtalk`,`email`,`department`,`position`,`home_address`,`is_primary`,`status`,`remark`,`create_time`,`update_time`,`delete_time`) SELECT CAST(o.`tenant_id` AS CHAR), o.`company_type`, o.`company_id`, o.`name`, o.`gender`, o.`phone`, o.`mobiles`, IFNULL(o.`wechat`, ''''), IFNULL(o.`qq`, ''''), IFNULL(o.`dingtalk`, ''''), IFNULL(o.`email`, ''''), IFNULL(o.`department`, ''''), IFNULL(o.`position`, ''''), IFNULL(o.`home_address`, ''''), IFNULL(o.`is_primary`, 0), IFNULL(o.`status`, 1), o.`remark`, IFNULL(o.`create_time`, NOW()), IFNULL(o.`update_time`, NOW()), o.`delete_time` FROM `yz_backend_erp_company_contact` o WHERE NOT EXISTS ( SELECT 1 FROM `yz_backend_contact_company` n WHERE n.`tenant_id` = CAST(o.`tenant_id` AS CHAR) AND n.`company_type` = o.`company_type` AND n.`company_id` = o.`company_id` AND n.`name` = o.`name` AND IFNULL(n.`mobiles`, '''') = IFNULL(o.`mobiles`, '''') )', 'SELECT ''step3: 无并存旧公司联系人表,跳过合并'' AS note'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @bak_company_exists := ( SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'yz_backend_erp_company_contact_bak' ); SET @sql := IF(@has_old_company > 0 AND @bak_company_exists = 0, 'RENAME TABLE `yz_backend_erp_company_contact` TO `yz_backend_erp_company_contact_bak`', 'SELECT ''step3: 跳过改名备份'' AS note'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- ----------------------------------------------------------------------------- -- 4. 历史死表 yz_tenant_crm_contact(related_type 1=客户/2=供应商)→ 新表,原表备份 -- mobiles 由单个 mobile 转为 JSON 数组;相关字段做空值兜底。 -- ----------------------------------------------------------------------------- SET @has_dead := ( SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'yz_tenant_crm_contact' ); SET @sql := IF(@has_dead > 0, 'INSERT INTO `yz_backend_contact_company` (`tenant_id`,`company_type`,`company_id`,`name`,`gender`,`phone`,`mobiles`,`wechat`,`qq`,`dingtalk`,`email`,`department`,`position`,`home_address`,`is_primary`,`status`,`remark`,`create_time`,`update_time`,`delete_time`) SELECT CAST(o.`tenant_id` AS CHAR), IF(o.`related_type` = 2, ''supplier'', ''customer''), o.`related_id`, o.`contact_name`, IFNULL(o.`gender`, 0), IFNULL(o.`phone`, ''''), CASE WHEN o.`mobile` IS NULL OR o.`mobile` = '''' THEN NULL ELSE CONCAT(''["'', o.`mobile`, ''"]'') END, '''', '''', '''', IFNULL(o.`email`, ''''), IFNULL(o.`department`, ''''), IFNULL(o.`position`, ''''), '''', IFNULL(o.`is_primary`, 0), 1, IFNULL(o.`remark`, ''''), IFNULL(o.`create_time`, NOW()), IFNULL(o.`update_time`, NOW()), CASE WHEN IFNULL(o.`is_deleted`, 0) = 1 THEN NOW() ELSE NULL END FROM `yz_tenant_crm_contact` o WHERE o.`contact_name` IS NOT NULL AND o.`contact_name` <> '''' AND NOT EXISTS ( SELECT 1 FROM `yz_backend_contact_company` n WHERE n.`tenant_id` = CAST(o.`tenant_id` AS CHAR) AND n.`company_type` = IF(o.`related_type` = 2, ''supplier'', ''customer'') AND n.`company_id` = o.`related_id` AND n.`name` = o.`contact_name` AND IFNULL(n.`mobiles`, '''') = IFNULL( CASE WHEN o.`mobile` IS NULL OR o.`mobile` = '''' THEN NULL ELSE CONCAT(''["'', o.`mobile`, ''"]'') END, '''') )', 'SELECT ''步骤4: 无 yz_tenant_crm_contact,跳过'' AS note'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @bak_dead_exists := ( SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'yz_tenant_crm_contact_bak' ); SET @sql := IF(@has_dead > 0 AND @bak_dead_exists = 0, 'RENAME TABLE `yz_tenant_crm_contact` TO `yz_tenant_crm_contact_bak`', 'SELECT ''步骤4: 跳过改名备份'' AS note'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- ----------------------------------------------------------------------------- -- 5. 重复数据检测(只查询、不修改/不删除,供人工核对) -- ----------------------------------------------------------------------------- SELECT `tenant_id`, `company_type`, `company_id`, `name`, IFNULL(`mobiles`, '') AS `mobiles`, COUNT(*) AS `dup_count`, GROUP_CONCAT(`id` ORDER BY `id`) AS `dup_ids` FROM `yz_backend_contact_company` WHERE `delete_time` IS NULL GROUP BY `tenant_id`, `company_type`, `company_id`, `name`, IFNULL(`mobiles`, '') HAVING COUNT(*) > 1; -- ----------------------------------------------------------------------------- -- 6. 迁移结果核对(新表与备份表条数) -- ----------------------------------------------------------------------------- SET @bak_company_exists2 := ( SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'yz_backend_erp_company_contact_bak' ); SET @bak_dead_exists2 := ( SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'yz_tenant_crm_contact_bak' ); SELECT 'yz_backend_contact_company' AS `table_name`, COUNT(*) AS `row_count` FROM `yz_backend_contact_company`; SET @sql := IF(@bak_company_exists2 > 0, 'SELECT ''yz_backend_erp_company_contact_bak'' AS `table_name`, COUNT(*) AS `row_count` FROM `yz_backend_erp_company_contact_bak`', 'SELECT ''yz_backend_erp_company_contact_bak(不存在)'' AS `table_name`, 0 AS `row_count`'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF(@bak_dead_exists2 > 0, 'SELECT ''yz_tenant_crm_contact_bak'' AS `table_name`, COUNT(*) AS `row_count` FROM `yz_tenant_crm_contact_bak`', 'SELECT ''yz_tenant_crm_contact_bak(不存在)'' AS `table_name`, 0 AS `row_count`'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;