当前位置: 首页 > news >正文

SqlServer 按时间-日期自动分表

1. 创建主表

首先,创建主表 MainTable

CREATE TABLE MainTable (ID INT PRIMARY KEY,Data VARCHAR(100),CreateTime DATETIME
);

2. 创建触发器

在高并发环境下,可能会出现多个插入操作同时触发触发器,导致多个事务尝试同时创建同一个分表的情况。需要确保在创建分表时使用事务和锁定机制来防止并发冲突。

2.1 insert 触发器

CREATE TRIGGER AutoSplitTable
ON MainTable
AFTER INSERT
AS
BEGINSET NOCOUNT ON;DECLARE @YearMonth CHAR(6);DECLARE @TableName NVARCHAR(50);DECLARE @DynamicSQL NVARCHAR(MAX);-- 声明变量用于游标中的每一行DECLARE @ID INT;DECLARE @Data VARCHAR(100);DECLARE @CreateTime DATETIME;-- 使用游标遍历插入的数据行DECLARE InsertedCursor CURSOR FORSELECT FORMAT(CreateTime, 'yyyyMM') AS YearMonth, ID, Data, CreateTimeFROM inserted;OPEN InsertedCursor;FETCH NEXT FROM InsertedCursor INTO @YearMonth, @ID, @Data, @CreateTime;WHILE @@FETCH_STATUS = 0BEGINSET @TableName = N'MainTable_' + @YearMonth;-- 检查目标分表是否存在,如果不存在则创建IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = @TableName)BEGINBEGIN TRANSACTION;BEGIN TRY-- 再次检查以确保分表不会被其他并发事务创建IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = @TableName)BEGINSET @DynamicSQL = N'CREATE TABLE ' + @TableName + ' (ID INT PRIMARY KEY,Data VARCHAR(100),CreateTime DATETIME)';EXEC sp_executesql @DynamicSQL;ENDCOMMIT TRANSACTION;END TRYBEGIN CATCHROLLBACK TRANSACTION;THROW;END CATCHEND-- 动态插入数据到目标分表SET @DynamicSQL = N'INSERT INTO ' + @TableName + ' (ID, Data, CreateTime)VALUES (@ID, @Data, @CreateTime)';EXEC sp_executesql @DynamicSQL, N'@ID INT, @Data VARCHAR(100), @CreateTime DATETIME', @ID, @Data, @CreateTime;FETCH NEXT FROM InsertedCursor INTO @YearMonth, @ID, @Data, @CreateTime;ENDCLOSE InsertedCursor;DEALLOCATE InsertedCursor;
END;

 2.2 update 触发器

CREATE TRIGGER AutoSplitTable_Update
ON MainTable
AFTER UPDATE
AS
BEGINSET NOCOUNT ON;DECLARE @YearMonth CHAR(6);DECLARE @TableName NVARCHAR(50);DECLARE @DynamicSQL NVARCHAR(MAX);DECLARE @ID INT;DECLARE @Data VARCHAR(100);DECLARE @CreateTime DATETIME;DECLARE UpdatedCursor CURSOR FORSELECT FORMAT(CreateTime, 'yyyyMM') AS YearMonth, ID, Data, CreateTimeFROM inserted;OPEN UpdatedCursor;FETCH NEXT FROM UpdatedCursor INTO @YearMonth, @ID, @Data, @CreateTime;WHILE @@FETCH_STATUS = 0BEGINSET @TableName = N'MainTable_' + @YearMonth;-- 检查目标分表是否存在,如果不存在则创建IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = @TableName)BEGINBEGIN TRANSACTION;BEGIN TRY-- 再次检查以确保分表不会被其他并发事务创建IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = @TableName)BEGINSET @DynamicSQL = N'CREATE TABLE ' + @TableName + ' (ID INT PRIMARY KEY,Data VARCHAR(100),CreateTime DATETIME)';EXEC sp_executesql @DynamicSQL;ENDCOMMIT TRANSACTION;END TRYBEGIN CATCHROLLBACK TRANSACTION;THROW;END CATCHEND-- 动态更新目标分表的数据SET @DynamicSQL = N'UPDATE ' + @TableName + ' SET Data = @Data, CreateTime = @CreateTimeWHERE ID = @ID';EXEC sp_executesql @DynamicSQL, N'@ID INT, @Data VARCHAR(100), @CreateTime DATETIME', @ID, @Data, @CreateTime;FETCH NEXT FROM UpdatedCursor INTO @YearMonth, @ID, @Data, @CreateTime;ENDCLOSE UpdatedCursor;DEALLOCATE UpdatedCursor;
END;

 2.3 delete 触发器 

CREATE TRIGGER AutoSplitTable_Delete
ON MainTable
AFTER DELETE
AS
BEGINSET NOCOUNT ON;DECLARE @YearMonth CHAR(6);DECLARE @TableName NVARCHAR(50);DECLARE @DynamicSQL NVARCHAR(MAX);DECLARE @ID INT;DECLARE @CreateTime DATETIME;DECLARE DeletedCursor CURSOR FORSELECT FORMAT(CreateTime, 'yyyyMM') AS YearMonth, ID, CreateTimeFROM deleted;OPEN DeletedCursor;FETCH NEXT FROM DeletedCursor INTO @YearMonth, @ID, @CreateTime;WHILE @@FETCH_STATUS = 0BEGINSET @TableName = N'MainTable_' + @YearMonth;-- 动态删除目标分表的数据SET @DynamicSQL = N'DELETE FROM ' + @TableName + ' WHERE ID = @ID';EXEC sp_executesql @DynamicSQL, N'@ID INT', @ID;FETCH NEXT FROM DeletedCursor INTO @YearMonth, @ID, @CreateTime;ENDCLOSE DeletedCursor;DEALLOCATE DeletedCursor;
END;

测试触发器

通过向 MainTable 插入数据来测试触发器的效果:

-- 插入数据
INSERT INTO MainTable (ID, Data, CreateTime)
VALUES (1, 'Sample Data 1', '2023-01-15'),(2, 'Sample Data 2', '2023-02-20'),(3, 'Sample Data 3', '2023-03-25');-- 检查分表
SELECT * FROM DetailTable_202301;
SELECT * FROM DetailTable_202302;
SELECT * FROM DetailTable_202303;

结论

通过上述步骤,可以实现基于月份的自动分表策略,自动将插入到 MainTable 的数据按照创建时间分到相应的分表中。触发器和动态 SQL 的结合确保了数据的分表和插入过程的自动化,同时通过事务处理并发插入的情况。

注意

使用触发器进行分表操作可能存在效率问题,特别是在数据插入、更新、删除操作频繁的情况下。这是因为触发器会在每次相关操作时执行,可能导致性能瓶颈和锁定问题。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【人工智能】人工智能可解释性和透明度的详细探讨
  • C# 串口通讯怎么防止数据丢失
  • C语言:设计模式
  • 嵌入式 Linux 系统中的常用文件系统及应用场景
  • 数理基础知识
  • vue3中图片引入
  • Apache Curator 创建节点时,如果节点存储就会抛出异常吗?
  • 正点原子imx6ull-mini-Linux驱动之Linux IIO 驱动实验
  • 计算机网络408考研 2021
  • C++ Rect And Point Search Algorithm
  • CORS与JSONP漏洞原理及其复现
  • 模拟退火的
  • WebRTC ICE配置类型
  • MySQL使用(表)
  • 【零基础实战】基于物联网的人工淡水湖养殖系统设计
  • centos安装java运行环境jdk+tomcat
  • golang中接口赋值与方法集
  • WePY 在小程序性能调优上做出的探究
  • 多线程 start 和 run 方法到底有什么区别?
  • 普通函数和构造函数的区别
  • 前端路由实现-history
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • nb
  • 你对linux中grep命令知道多少?
  • PostgreSQL之连接数修改
  • # Java NIO(一)FileChannel
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • #WEB前端(HTML属性)
  • #前后端分离# 头条发布系统
  • (3) cmake编译多个cpp文件
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (强烈推荐)移动端音视频从零到上手(上)
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (一)基于IDEA的JAVA基础10
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转)c++ std::pair 与 std::make
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .Net Core缓存组件(MemoryCache)源码解析
  • .net dataexcel 脚本公式 函数源码
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET WebClient 类下载部分文件会错误?可能是解压缩的锅
  • .NET开发不可不知、不可不用的辅助类(一)
  • @Transactional 详解
  • [【JSON2WEB】 13 基于REST2SQL 和 Amis 的 SQL 查询分析器
  • [④ADRV902x]: Digital Filter Configuration(发射端)
  • [Android]使用Retrofit进行网络请求
  • [ASP]青辰网络考试管理系统NES X3.5
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [BZOJ1877][SDOI2009]晨跑[最大流+费用流]