T-SQL Recipes之Organizing and Archiving Data
The Problem
当我们处理存档数据或内存数据时,我们想要自定义命名表名,数据库,架构加上日期,时间,或者应用名时,用标准的TSQL来实现是比较困难的。
假设我们有一张日志表,增长速度异常快。但是你不需要超过一个星期的数据,应该怎么做呢?
表分区当然是最佳选择了,但只有企业版里面有这项功能,难道我们就没有其他选择了吗?当然是有的,先来准备点数据吧。
准备数据:
USE AdventureWorks2014;
GO
IF OBJECT_ID('dbo.Database_Log') IS NOT NULL
BEGIN
DROP TABLE dbo.Database_Log
END CREATE TABLE dbo.Database_Log
(
log_id INT NOT NULL
IDENTITY(1, 1)
CONSTRAINT PK_Database_Log PRIMARY KEY CLUSTERED ,
Log_Time DATETIME ,
Log_Data NVARCHAR(1000)
); DECLARE @datetime DATETIME = CURRENT_TIMESTAMP;
DECLARE @datediff TABLE
(
previous_hour SMALLINT
); DECLARE @count SMALLINT = 0;
WHILE @count <= 360
BEGIN
INSERT INTO @datediff
( previous_hour )
SELECT @count;
SELECT @count = @count + 1
END
SELECT @count = 0;
WHILE @count <= 1000
BEGIN
INSERT INTO Database_Log
( Log_Time ,
Log_Data
)
SELECT DATEADD(HOUR, -1 * previous_hour, CURRENT_TIMESTAMP) ,
CAST(DATEADD(HOUR, -1 * previous_hour,
CURRENT_TIMESTAMP) AS NVARCHAR)
FROM @datediff;
SELECT @count = @count + 1;
END
DECLARE @year_offset TINYINT = 5;
WHILE @year_offset > 0
BEGIN
INSERT INTO dbo.Database_Log
( Log_Time ,
Log_Data
)
SELECT TOP 10000
DATEADD(YEAR, -1 * @year_offset, Log_Time) ,
CAST(DATEADD(YEAR, -1 * @year_offset, Log_Time) AS NVARCHAR)
FROM Database_Log
SELECT @year_offset = @year_offset - 1;
END
The Solution
假设我们存档数据格式是,每年为数据库,每星期为一个表。如:dbo.database_log_2016为数据库,其中 dbo.database_log_2016_32为表。
我们动态SQL应该如何实现呢? 先整理一下思路
- 获取日志记录通过时间段
- 创建数据库或表(如果他们不存在)
- 进行插入操作
- 删除原始数据
代码:
DECLARE @sql_command NVARCHAR(MAX);
DECLARE @parameter_list NVARCHAR(MAX) = '@start_of_week DATETIME, @end_of_week DATETIME';
DECLARE @min_datetime DATETIME; SELECT @min_datetime = MIN(Log_Time)
FROM Database_Log; DECLARE @previous_min_time DATETIME = '1/1/1900';
DECLARE @start_of_week DATETIME = CAST(DATEADD(dd, -1 * (DATEPART(dw, @min_datetime) - 1), @min_datetime) AS DATE);
DECLARE @end_of_week DATETIME = DATEADD(WEEK, 1, @start_of_week);
DECLARE @current_year SMALLINT;
DECLARE @current_week TINYINT;
DECLARE @database_name NVARCHAR(128);
DECLARE @table_name NVARCHAR(128); WHILE (@previous_min_time <> @min_datetime)
BEGIN
SELECT @current_year = DATEPART(YEAR, @start_of_week);
SELECT @current_week = DATEPART(WEEK, @start_of_week);
SELECT @database_name = 'Database_Log_' + CAST(@current_year AS NVARCHAR); -- Create the yearly database if it does not already exist
SELECT @table_name = 'Database_Log_' + CAST(@current_year AS NVARCHAR) + '_' + CAST(@current_week AS NVARCHAR)
IF NOT EXISTS(SELECT *FROM sys.databases WHERE databases.name = @database_name)
BEGIN
SELECT @sql_command = 'CREATE DATABASE [' + @database_name + ']';
EXEC sp_executesql @sql_command; END -- Create the weekly table if it does not already exist
SELECT @sql_command = '
USE [' + @database_name + '];
IF NOT EXISTS (SELECT * FROM sys.tables WHERE tables.name = ''' + @table_name + ''')
BEGIN
CREATE TABLE [dbo].[' + @table_name + ']
(Log_Id INT NOT NULL CONSTRAINT PK_Database_Log_' + CAST(@current_year AS NVARCHAR) + '_' + CAST(@current_week AS NVARCHAR) + ' PRIMARY KEY CLUSTERED,
Log_Time DATETIME,
Log_Data NVARCHAR(1000));
END' EXEC sp_executesql @sql_command; SELECT @sql_command = '
INSERT INTO [' + @database_name + '].[dbo].[' + @table_name + ']
(Log_Id, Log_Time, Log_Data) SELECT
Log_Id,
Log_Time,
Log_Data
FROM AdventureWorks2014.dbo.Database_Log
WHERE
Log_Time >= @start_of_week
AND Log_Time <= @end_of_week
AND Log_Time < DATEADD(WEEK, -1, CURRENT_TIMESTAMP); DELETE
FROM AdventureWorks2014.dbo.Database_Log
WHERE
Log_Time >= @start_of_week
AND Log_Time <= @end_of_week
AND Log_Time < DATEADD(WEEK, -1, CURRENT_TIMESTAMP);' EXEC sp_executesql @sql_command,@parameter_list,@start_of_week,@end_of_week SELECT @previous_min_time = @min_datetime; SELECT @min_datetime = MIN(Log_Time)
FROM Database_Log; SELECT @start_of_week = CAST(DATEADD(dd, -1 * (DATEPART(dw, @min_datetime) - 1), @min_datetime) AS DATE); SELECT @end_of_week = DATEADD(WEEK, 1, @start_of_week); END
结语
善使用动态TSQL会让你在工作中的心情变得更美好,当然也可能更恶劣。以后还会讲到如何使用动态TSQL来备份数据库,索引管理。
T-SQL Recipes之Organizing and Archiving Data的更多相关文章
- SQL2008安装时,“provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接) (.Net SqlClient Data Provider)” 错误的解决方案
错误提示: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provide ...
- SQL Fundamentals:Restricting and Sorting Data限制和排序数据(FROM-WHERE-SELECT-ORDER BY)
SQL Fundamentals || Oracle SQL语言 控制操作的显示列:基本的SELECT语句 控制行:限定查询和排序显示 分组统计查询 限定查询:WHERE字句 排序显示:ORDER B ...
- SQL Server2008 错误源:.net SqlClient data provider的解决方法
今天下午直接在SQL Server 2008的Microsoft SQL Server Management Studio 中修改一张表中某个字段, 不管是删除字符还是添加都提示下面的错误. 网上很多 ...
- 20180820 SQL 提示Error: String or binary data would be truncated
Error: String or binary data would be truncated,错误,是因为栏位给出的长度不够,增加初始化长度就可以了. 除了创建表的增加长度情况,还有一种是,SELE ...
- 未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: Named Pipes Provider, error: 40 - 无法打开到 SQL Server 的连接) (.Net SqlClient Data Provider)
今天连接服务器的SQL Server 遇到了一个很经典的问题 之前也曾多次遇到过 这次记录一下 按照之前经验 首先 开启了服务中的 SQL Server(MSSQLSERVER)和ASP.NET St ...
- Spark SQL External Data Sources JDBC简易实现
在spark1.2版本中最令我期待的功能是External Data Sources,通过该API可以直接将External Data Sources注册成一个临时表,该表可以和已经存在的表等通过sq ...
- 转载:Character data is represented incorrectly when the code page of the client computer differs from the code page of the database in SQL Server 2005
https://support.microsoft.com/en-us/kb/904803 Character data is represented incorrectly when the cod ...
- sql是如何执行一个查询的!
引用自:http://rusanu.com/2013/08/01/understanding-how-sql-server-executes-a-query/ Understanding how SQ ...
- [Windows Azure] Data Management and Business Analytics
http://www.windowsazure.com/en-us/develop/net/fundamentals/cloud-storage/ Managing and analyzing dat ...
随机推荐
- ubuntu 15.10 安装swift开发环境 2016/4/17
ubuntu 15.10 64位 下载地址 https://swift.org/download/#using-downloads 1.首先在ubuntu终端上 (ctl+alt+t打开) 下载cla ...
- Linux下编译安装MariaDB
MariaDB是MySQL的一个开源分支,主要是社区在维护,并且完全兼容MySQL,并且可以很方便的称为MySQL的替代,MariaDB的诞生正是出自MySQL创始人Michael Widenius之 ...
- windows 中去除Ctrl+Alt+Del才能登录
安装windows 7后登录的时候有一样很麻烦的步骤是需要先按Ctrl+Alt+Del,才能输入用户密码进行登录.这里笔者介绍一下如何取消这个东西. 点击“开始菜单”,点击“控制面板”. [管理工具] ...
- linux下php-mysql拓展安装
今天遇到一个奇怪的问题: 在服务器A上部署应用,在服务器B上部署数据库和缓存. 服务器A:apache2.2,php5.3 服务器B:mysql5.5,redis2.4 问题现象: 本地远程连接服务器 ...
- STM32F412应用开发笔记之二:基本GPIO控制
NUCLEO-F412ZG板子上的元器件并没有完全焊接,除去ST-LINK部分和电源部分后,还有用一个USB主机接口,三个LED灯和两个按钮,不过很多功能引脚都已经引到了插针.查看原理图可发现,由原理 ...
- swift错误 Expressions are not allowed at the top level
``` ... earlier we said top-level code isn't allowed in most of your app's source files. The excepti ...
- ffmpeg 常用命令
mp4中的h264编码,而h264有两种封装: 一种是annexb模式,传统模式,有startcode,SPS和PPS是在ES中:另一种是mp4模式,一般mp4.mkv.avi会没有startcode ...
- oracleDBA-D4
1.数据字典: 创建和维护的可修改的系统表..它存放有关数据库和数据库对象的信息. 数据字典=基表+字典视图 2.数据字典所存放的信息: 数据库的逻辑和物理结构(如:表空间和数据文件),数据对象定义的 ...
- MFC 创建多层目录
创建多层目录 BOOL CTestToolCtr::CreateFolder(CString strNewFolder) { /************************************ ...
- Vue.js 快速入门
什么是Vue.js vue是法语中视图的意思,Vue.js是一个轻巧.高性能.可组件化的MVVM库,同时拥有非常容易上手的API.作者是尤雨溪,写下这篇文章时vue.js版本为1.0.7 准备 我推荐 ...