/* CQMS/Check、CQMS/Technical 专属对象清理脚本 已按用户要求确认数据库此前已备份,本脚本不执行备份。 保留对象: - WBS 共享:Check_CheckControl、Check_CheckControlApprove、 Check_SpotCheck、Check_SpotCheckApprove、Check_SpotCheckDetail - 焊接共享:Check_CheckMonth、Check_MonthNDTCheck、Check_MonthWelder - 共享质量数据:Project_CQMSData_CQMS 等表 删除对象: - CQMS/Check、CQMS/Technical 的专属表、视图、旧存储过程 - 已下线的 CQMS 质量月报汇总采集表及其存储过程 - 对应菜单、按钮映射、流程权限和角色权限 使用方式:在确认执行窗口后,于目标数据库执行整份脚本。 脚本具备重复执行保护;若发现保护表缺失,会在删除前终止。 */ USE [SGGLDB_SHJ]; GO SET NOCOUNT ON; SET XACT_ABORT ON; IF DB_NAME() <> N'SGGLDB_SHJ' BEGIN RAISERROR(N'当前数据库不是 SGGLDB_SHJ,已停止执行。', 16, 1); RETURN; END; DECLARE @ProtectedTables TABLE ( TableName sysname NOT NULL PRIMARY KEY, ProtectionNote nvarchar(200) NOT NULL ); INSERT INTO @ProtectedTables (TableName, ProtectionNote) VALUES (N'Check_CheckControl', N'WBS 质量问题及控制点'), (N'Check_CheckControlApprove', N'WBS 质量问题审批'), (N'Check_SpotCheck', N'WBS 实体验收'), (N'Check_SpotCheckApprove', N'WBS 实体验收审批'), (N'Check_SpotCheckDetail', N'WBS 实体验收明细'), (N'Check_CheckMonth', N'焊接共享月度数据'), (N'Check_MonthNDTCheck', N'焊接月度无损检测数据'), (N'Check_MonthWelder', N'焊接月度焊工数据'); IF EXISTS ( SELECT 1 FROM @ProtectedTables AS p WHERE OBJECT_ID(N'dbo.' + p.TableName, N'U') IS NULL ) BEGIN SELECT p.TableName, p.ProtectionNote FROM @ProtectedTables AS p WHERE OBJECT_ID(N'dbo.' + p.TableName, N'U') IS NULL; RAISERROR(N'保护表不完整,已停止执行。', 16, 1); RETURN; END; DECLARE @DropTables TABLE ( TableName sysname NOT NULL PRIMARY KEY, CleanupGroup nvarchar(100) NOT NULL ); INSERT INTO @DropTables (TableName, CleanupGroup) VALUES (N'Check_CheckEquipment', N'检试验设备'), (N'Check_CheckEquipmentApprove', N'检试验设备审批'), (N'Check_Design', N'设计变更'), (N'Check_DesignApprove', N'设计变更审批'), (N'Check_Draw', N'图纸管理'), (N'Check_DrawApprove', N'图纸审批'), (N'Check_JointCheck', N'质量共检'), (N'Check_JointCheckApprove', N'质量共检审批'), (N'Check_JointCheckDetail', N'质量共检明细'), (N'Check_MaterialAcceptance', N'材料验收'), (N'Check_MonthDesign', N'月报设计变更'), (N'Check_MonthRectify', N'月报质量整改'), (N'Check_MonthSpotCheckDetail', N'月报质量验收'), (N'Check_SpecialEquipmentDetail', N'特种设备月报'), (N'Check_TechnicalContactList', N'工程联络单'), (N'Check_TechnicalContactListApprove', N'工程联络单审批'), (N'Technical_TechnicalDisclose', N'施工技术交底'), (N'DigData_CQMSDataCollect', N'旧 CQMS 质量汇总'), (N'DigData_CQMSDataCollectItem', N'旧 CQMS 质量汇总明细'), (N'DigData_CQMSDataCollectSubmission', N'旧 CQMS 质量月报提交'); DECLARE @DropViews TABLE ( ObjectName sysname NOT NULL PRIMARY KEY ); INSERT INTO @DropViews (ObjectName) VALUES (N'View_Check_JointCheckDetail'); DECLARE @DropProcedures TABLE ( ObjectName sysname NOT NULL PRIMARY KEY ); INSERT INTO @DropProcedures (ObjectName) VALUES (N'SpAuditingManage'), (N'SpAuditingManageByProjectId'), (N'SpEnableCueQuality'), (N'SpEnableCueQualityByPrject'), (N'SpNotice'), (N'SpNoticeByProjectId'), (N'Sp_DigData_CQMSDataCollect'); DECLARE @DropMenuIds TABLE ( MenuId nvarchar(100) NOT NULL PRIMARY KEY, MenuName nvarchar(100) NOT NULL ); /* 静态清单对应当前 Menu_CQMS.xml 中已删除的节点;保留质量数据共享节点。 */ INSERT INTO @DropMenuIds (MenuId, MenuName) VALUES (N'31B86B12-632D-4DDD-B937-E21CA6A88537', N'检试验设备管理'), (N'BB8EB284-A014-442E-A1D7-956AA11272AE', N'检试验设备'), (N'1011063B-FEAC-4B89-A9D9-0F9F6BB3328E', N'施工技术交底管理'), (N'F0D0B2C6-51ED-4C47-95EB-C3DCB639BA5F', N'施工技术交底'), (N'B8500D87-407E-458C-9915-FD54F0E81F36', N'质量验收'), (N'CC43E208-335D-4AE3-A1CE-B2D8510AE854', N'实体验收'), (N'8317C0F7-3A69-48AB-87E5-03E96C543B1C', N'资料验收'), (N'1433BE70-13C0-4AC7-BC3D-34C9471CE2A8', N'质量验收统计'), (N'A54EC449-5F77-4068-83B9-AA305B721A0B', N'质量检查'), (N'B3E99BD9-FDC7-4F15-8C3C-A7821AC9E306', N'质量巡检'), (N'E6703F32-4E42-4D03-84B3-5EC0E8E48E0F', N'质量共检'), (N'D3B1433E-00DE-432B-A30A-0EFB513480A8', N'问题统计'), (N'786864C0-2875-49CD-B55E-0B5C8253295D', N'质量月报'), (N'390A78F0-43B2-4AF1-81B9-7C216FA7E0A4', N'文件柜'), (N'CF33572A-E875-4492-92BF-6EA265909A6C', N'质量共检通知单'), (N'8D5A7D48-21C0-4668-9E70-813AE9C523FA', N'施工质量问题整改单'), (N'0E6E6022-356E-42A1-9D16-C75BF69EBFB5', N'施工质量检查记录'), (N'3354E9AA-8D71-401B-9CFC-03D69DA86B05', N'工程联络单'), (N'A68445D0-78BB-4E67-93FC-606DECA0B585', N'设计变更统计表'), (N'0A54D274-547C-4555-9D00-D8D5034E8849', N'质量月报'), (N'03CEB246-0CE5-48CB-9D6B-1B84AC2E27B3', N'重要文件'); /* 补充清理数据库中仍残留的目标 URL 菜单,并递归收集目标节点的子菜单。 */ INSERT INTO @DropMenuIds (MenuId, MenuName) SELECT m.MenuId, ISNULL(m.MenuName, N'CQMS/Check 或 CQMS/Technical 残留菜单') FROM dbo.Sys_Menu AS m WHERE (m.Url LIKE N'CQMS/Check/%' OR m.Url LIKE N'CQMS/Technical/%') AND NOT EXISTS (SELECT 1 FROM @DropMenuIds AS d WHERE d.MenuId = m.MenuId); WHILE 1 = 1 BEGIN INSERT INTO @DropMenuIds (MenuId, MenuName) SELECT m.MenuId, ISNULL(m.MenuName, N'目标菜单子节点') FROM dbo.Sys_Menu AS m JOIN @DropMenuIds AS d ON d.MenuId = m.SuperMenu WHERE NOT EXISTS (SELECT 1 FROM @DropMenuIds AS x WHERE x.MenuId = m.MenuId); IF @@ROWCOUNT = 0 BREAK; END; SELECT N'待删除菜单' AS ItemType, MenuId, MenuName FROM @DropMenuIds ORDER BY MenuId; SELECT N'待删除表' AS ItemType, d.TableName, d.CleanupGroup, ObjectType = o.type_desc, TableRows = ISNULL(p.TableRows, 0) FROM @DropTables AS d LEFT JOIN sys.objects AS o ON o.object_id = OBJECT_ID(N'dbo.' + d.TableName) OUTER APPLY ( SELECT SUM(sp.rows) AS TableRows FROM sys.partitions AS sp WHERE sp.object_id = o.object_id AND sp.index_id IN (0, 1) ) AS p ORDER BY d.TableName; BEGIN TRY BEGIN TRANSACTION; /* 菜单相关流程、按钮映射、按钮权限和角色权限先于菜单删除。 */ DELETE FROM dbo.Sys_MenuFlowOperate WHERE MenuId IN (SELECT MenuId FROM @DropMenuIds); DELETE FROM dbo.Sys_ButtonPower WHERE MenuId IN (SELECT MenuId FROM @DropMenuIds) OR ButtonToMenuId IN (SELECT MenuId FROM @DropMenuIds); DELETE FROM dbo.Sys_ButtonToMenu WHERE MenuId IN (SELECT MenuId FROM @DropMenuIds); DELETE FROM dbo.Sys_RolePower WHERE MenuId IN (SELECT MenuId FROM @DropMenuIds); DELETE FROM dbo.Sys_Menu WHERE MenuId IN (SELECT MenuId FROM @DropMenuIds) OR Url LIKE N'CQMS/Check/%' OR Url LIKE N'CQMS/Technical/%'; /* 删除仅服务于已下线模块的视图和存储过程。 */ DECLARE @ObjectName sysname; DECLARE object_cursor CURSOR LOCAL FAST_FORWARD FOR SELECT ObjectName FROM @DropViews WHERE OBJECT_ID(N'dbo.' + ObjectName, N'V') IS NOT NULL UNION ALL SELECT ObjectName FROM @DropProcedures WHERE OBJECT_ID(N'dbo.' + ObjectName, N'P') IS NOT NULL; OPEN object_cursor; FETCH NEXT FROM object_cursor INTO @ObjectName; WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @DropObjectSql nvarchar(max) = N'DROP ' + CASE WHEN EXISTS (SELECT 1 FROM @DropViews WHERE ObjectName = @ObjectName) THEN N'VIEW ' ELSE N'PROCEDURE ' END + QUOTENAME(N'dbo') + N'.' + QUOTENAME(@ObjectName) + N';'; EXEC sys.sp_executesql @DropObjectSql; FETCH NEXT FROM object_cursor INTO @ObjectName; END; CLOSE object_cursor; DEALLOCATE object_cursor; /* 删除目标表涉及的全部外键,保护表本身不会进入 @DropTables。 */ DECLARE @ForeignKeyName sysname; DECLARE @ParentSchema sysname; DECLARE @ParentTable sysname; DECLARE foreign_key_cursor CURSOR LOCAL FAST_FORWARD FOR SELECT fk.name, OBJECT_SCHEMA_NAME(fk.parent_object_id), OBJECT_NAME(fk.parent_object_id) FROM sys.foreign_keys AS fk WHERE OBJECT_NAME(fk.parent_object_id) IN (SELECT TableName FROM @DropTables) OR OBJECT_NAME(fk.referenced_object_id) IN (SELECT TableName FROM @DropTables); OPEN foreign_key_cursor; FETCH NEXT FROM foreign_key_cursor INTO @ForeignKeyName, @ParentSchema, @ParentTable; WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @DropForeignKeySql nvarchar(max) = N'ALTER TABLE ' + QUOTENAME(@ParentSchema) + N'.' + QUOTENAME(@ParentTable) + N' DROP CONSTRAINT ' + QUOTENAME(@ForeignKeyName) + N';'; EXEC sys.sp_executesql @DropForeignKeySql; FETCH NEXT FROM foreign_key_cursor INTO @ForeignKeyName, @ParentSchema, @ParentTable; END; CLOSE foreign_key_cursor; DEALLOCATE foreign_key_cursor; DECLARE @TableName sysname; DECLARE table_cursor CURSOR LOCAL FAST_FORWARD FOR SELECT TableName FROM @DropTables WHERE OBJECT_ID(N'dbo.' + TableName, N'U') IS NOT NULL; OPEN table_cursor; FETCH NEXT FROM table_cursor INTO @TableName; WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @DropTableSql nvarchar(max) = N'DROP TABLE ' + QUOTENAME(N'dbo') + N'.' + QUOTENAME(@TableName) + N';'; EXEC sys.sp_executesql @DropTableSql; FETCH NEXT FROM table_cursor INTO @TableName; END; CLOSE table_cursor; DEALLOCATE table_cursor; COMMIT TRANSACTION; END TRY BEGIN CATCH IF XACT_STATE() <> 0 ROLLBACK TRANSACTION; DECLARE @ErrorMessage nvarchar(4000) = ERROR_MESSAGE(); RAISERROR(@ErrorMessage, 16, 1); RETURN; END CATCH; SELECT N'清理后仍存在的目标表' AS ItemType, d.TableName FROM @DropTables AS d WHERE OBJECT_ID(N'dbo.' + d.TableName, N'U') IS NOT NULL ORDER BY d.TableName; SELECT N'清理后仍存在的目标菜单' AS ItemType, m.MenuId, m.MenuName, m.Url FROM dbo.Sys_Menu AS m WHERE m.Url LIKE N'CQMS/Check/%' OR m.Url LIKE N'CQMS/Technical/%' OR m.MenuId IN (SELECT MenuId FROM @DropMenuIds) ORDER BY m.MenuId; SELECT N'保留表确认' AS ItemType, p.TableName, p.ProtectionNote FROM @ProtectedTables AS p WHERE OBJECT_ID(N'dbo.' + p.TableName, N'U') IS NOT NULL ORDER BY p.TableName;