创建一个每月存储过程 (包含分表删除逻辑)+ SQL Server 代理作业(每月自动执行),支持按日期范围删除过期分表,且包含日志记录和安全校验。
步骤 1:创建删除分表的存储过程(带日志 + 安全校验)
sql
USE [你的数据库名]; -- 替换为分表所在数据库
GO
-- 创建删除日志表(记录次删除记录都将被记录,便于审计)
IF NOT EXISTS (SELECT 1 FROM sys.tables WHERE name = 'DropTableLog' AND schema_id = SCHEMA_ID('dbo'))
BEGIN
CREATE TABLE [dbo].[DropTableLog] (
LogId INT IDENTITY(1,1) PRIMARY KEY,
TableName NVARCHAR(100) NOT NULL, -- 被删除的表名
DropTime DATETIME NOT NULL DEFAULT GETDATE(), -- 删除时间
DropResult NVARCHAR(50) NOT NULL, -- 结果:成功/失败
ErrorMessage NVARCHAR(MAX) NULL -- 错误信息(失败时记录)
);
PRINT '已创建删除日志表:DropTableLog';
END
GO
-- 创建删除分表的存储过程
CREATE OR ALTER PROCEDURE [dbo].[sp_DropExpiredShardingTables]
@prefix NVARCHAR(50) = 'TestResultDetail', -- 分表前缀(如TestResultDetail)
@keepMonths INT = 6, -- 保留最近N个月的分表(超过则删除)
@tableCount INT = 3 -- 每月分表数量(如每月3张)
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@currentYearMonth NVARCHAR(6),
@expireYearMonth NVARCHAR(6), -- 过期年月(需删除的年月)
@j INT = 1,
@tableName NVARCHAR(100),
@sql NVARCHAR(MAX),
@errorMsg NVARCHAR(MAX);
-- 计算过期年月(当前时间减去保留月份)
SET @expireYearMonth = FORMAT(DATEADD(MONTH, -@keepMonths, GETDATE()), 'yyyyMM');
PRINT '开始删除 [' + @prefix + '] 前缀、' + @expireYearMonth + ' 及之前的分表...';
-- 从最早可能的分表年月开始遍历(这里从200001开始,可根据实际调整)
SET @currentYearMonth = '200001';
WHILE @currentYearMonth <= @expireYearMonth
BEGIN
SET @j = 1;
WHILE @j <= @tableCount
BEGIN
-- 生成分表名(如TestResultDetail2025111)
SET @tableName = @prefix + @currentYearMonth + CAST(@j AS NVARCHAR(1));
BEGIN TRY
-- 检查表是否存在
IF EXISTS (
SELECT 1 FROM sys.tables
WHERE name = @tableName AND schema_id = SCHEMA_ID('dbo')
)
BEGIN
-- 执行删除
SET @sql = N'DROP TABLE [dbo].[' + @tableName + N'];';
EXEC sp_executesql @sql;
-- 记录成功日志
INSERT INTO [dbo].[DropTableLog] (TableName, DropResult)
VALUES (@tableName, '成功');
PRINT '已删除表:' + @tableName;
END
ELSE
BEGIN
-- 表不存在,记录日志(可选)
INSERT INTO [dbo].[DropTableLog] (TableName, DropResult)
VALUES (@tableName, '表不存在,跳过');
PRINT '表不存在,跳过:' + @tableName;
END
END TRY
BEGIN CATCH
-- 捕获错误,记录日志
SET @errorMsg = ERROR_MESSAGE();
INSERT INTO [dbo].[DropTableLog] (TableName, DropResult, ErrorMessage)
VALUES (@tableName, '失败', @errorMsg);
PRINT '删除失败:' + @tableName + ',原因:' + @errorMsg;
END CATCH
SET @j = @j + 1;
END
-- 切换到下一个月(处理月份进位,如202512→202601)
SET @currentYearMonth = FORMAT(
DATEADD(MONTH, 1, CONVERT(DATETIME, @currentYearMonth + '01', 112)),
'yyyyMM'
);
END
PRINT '分表删除任务完成,详情请查看 DropTableLog 表';
END
GO
步骤 2:创建 SQL Server 代理作业(每月自动执行)
通过作业定期调用存储过程,实现每月自动删除过期分表。
方式 1:SSMS 图形界面创建
- 打开 SSMS,展开SQL Server 代理 → 右键作业 → 新建作业 :
-
常规 选项卡:
- 作业名称:
Job_DropExpiredShardingTables(自定义)。 - 描述:
每月删除过期的分表(保留最近6个月)。
- 作业名称:
-
步骤 选项卡:
-
新建步骤,名称:
Step1_ExecuteDrop。 -
数据库:选择分表所在的数据库。
-
命令: sql
-- 调用存储过程,保留最近6个月的分表(可调整参数) EXEC [dbo].[sp_DropExpiredShardingTables] @prefix = 'TestResultDetail', @keepMonths = 6, @tableCount = 3;
-
-
计划 选项卡:
- 新建计划,名称:
MonthlyLastDay(每月最后一天执行)。 - 频率:每月 ,执行时间:
23:00:00(避开业务高峰)。 - 高级:设置 "当月最后一天" 执行(需手动选择,或用 T-SQL 脚本设置)。
- 新建计划,名称:
-
- 保存作业。
方式 2:T-SQL 脚本创建作业(推荐,精确控制每月最后一天)
sql
USE [msdb];
GO
-- 创建作业
EXEC dbo.sp_add_job
@job_name = N'Job_DropExpiredShardingTables',
@enabled = 1,
@description = N'每月删除过期的分表(保留最近6个月)';
-- 创建作业步骤
EXEC dbo.sp_add_jobstep
@job_name = N'Job_DropExpiredShardingTables',
@step_name = N'Step1_ExecuteDrop',
@subsystem = N'TSQL',
@command = N'
EXEC [dbo].[sp_DropExpiredShardingTables]
@prefix = ''TestResultDetail'',
@keepMonths = 6,
@tableCount = 3;
',
@database_name = N'你的数据库名'; -- 替换为实际数据库名
-- 创建作业计划(每月最后一天23点执行)
EXEC dbo.sp_add_jobschedule
@job_name = N'Job_DropExpiredShardingTables',
@name = N'MonthlyLastDay_23h',
@freq_type = 16, -- 16=每月
@freq_interval = 1, -- 每月1次
@freq_recurrence_factor = 1, -- 每1个月
@active_start_time = 230000, -- 23:00:00
@freq_relative_interval = 16, -- 16=当月最后一天
@freq_interval = 0; -- 配合relative_interval使用
-- 关联到本地服务器
EXEC dbo.sp_add_jobserver
@job_name = N'Job_DropExpiredShardingTables',
@server_name = N'(local)';
GO
关键优化点
-
自动化与可控性:
- 通过
@keepMonths参数控制保留多久的分表(如保留 6 个月,自动删除更早的表),无需手动修改年月范围。 - 作业计划设为每月最后一天 23 点,避开业务高峰,减少对系统的影响。
- 通过
-
安全性与可追溯:
- 所有删除操作记录到
DropTableLog表,包含表名、时间、结果和错误信息,便于审计和排查问题。 - 异常捕获机制:单个表删除失败不会影响其他表,错误信息会被记录。
- 所有删除操作记录到
-
灵活性:
- 支持自定义分表前缀(
@prefix)、每月分表数量(@tableCount),适配不同分表规则。 - 如需调整保留时长,只需修改存储过程的
@keepMonths参数(如改为 3 个月)。
- 支持自定义分表前缀(
验证与维护
- 手动测试 :执行
EXEC [dbo].[sp_DropExpiredShardingTables] @keepMonths = 12;(保留 12 个月,避免误删),检查DropTableLog确认结果。 - 作业历史:通过作业的 "查看历史记录" 确认每月执行情况。
- 日志清理 :定期清理
DropTableLog表(如保留 1 年的日志),避免日志表过大。
此方案可长期稳定运行,自动清理过期分表,降低人工维护成本。