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的更多相关文章

  1. SQL2008安装时,“provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接) (.Net SqlClient Data Provider)” 错误的解决方案

    错误提示: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provide ...

  2. SQL Fundamentals:Restricting and Sorting Data限制和排序数据(FROM-WHERE-SELECT-ORDER BY)

    SQL Fundamentals || Oracle SQL语言 控制操作的显示列:基本的SELECT语句 控制行:限定查询和排序显示 分组统计查询 限定查询:WHERE字句 排序显示:ORDER B ...

  3. SQL Server2008 错误源:.net SqlClient data provider的解决方法

    今天下午直接在SQL Server 2008的Microsoft SQL Server Management Studio 中修改一张表中某个字段, 不管是删除字符还是添加都提示下面的错误. 网上很多 ...

  4. 20180820 SQL 提示Error: String or binary data would be truncated

    Error: String or binary data would be truncated,错误,是因为栏位给出的长度不够,增加初始化长度就可以了. 除了创建表的增加长度情况,还有一种是,SELE ...

  5. 未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: Named Pipes Provider, error: 40 - 无法打开到 SQL Server 的连接) (.Net SqlClient Data Provider)

    今天连接服务器的SQL Server 遇到了一个很经典的问题 之前也曾多次遇到过 这次记录一下 按照之前经验 首先 开启了服务中的 SQL Server(MSSQLSERVER)和ASP.NET St ...

  6. Spark SQL External Data Sources JDBC简易实现

    在spark1.2版本中最令我期待的功能是External Data Sources,通过该API可以直接将External Data Sources注册成一个临时表,该表可以和已经存在的表等通过sq ...

  7. 转载: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 ...

  8. sql是如何执行一个查询的!

    引用自:http://rusanu.com/2013/08/01/understanding-how-sql-server-executes-a-query/ Understanding how SQ ...

  9. [Windows Azure] Data Management and Business Analytics

    http://www.windowsazure.com/en-us/develop/net/fundamentals/cloud-storage/ Managing and analyzing dat ...

随机推荐

  1. JS学习:第二周——NO.3盒子模型

    1.CSS盒子模型包括四个部分组成:设定的宽高+padding+border+margin: 2.JS盒子模型:通过系统提供的属性和方法,来获取当前元素的样式值   JS提供的属性和方法: clien ...

  2. MySQL 优化数据库对象

    一.考虑是用 procedure analyse() 函数对当前应用的表进行分析.字段类型是否可优化. 二.通过拆分提高表的访问效率. (A) 针对MyISAM表,有两种拆分方法: 垂直拆分:主码和某 ...

  3. Authorization in Cloud Applications using AD Groups

    If you're a developer of a SaaS application that allows business users to create and share content – ...

  4. Python中操作mysql的pymysql模块详解

    Python中操作mysql的pymysql模块详解 前言 pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同.但目前pymysql支持python3.x而后者不支持 ...

  5. MFC2016.6.8

    1.theApp extern声明之后不可以使用?可以用,只是需要extern之后的类名和类名称写对,不要犯得低级错误.2.怎样取出列表控件中的第某列的值?GetItemText(); CListCt ...

  6. grep-2.26 sed-4.2.2 awk-4.1.4 wget-1.18 pcregrep-8.39 pcre2grep-10.22 for windows 最新版本静态编译

    -------------------------------------------------------------------------------------------- grep (G ...

  7. js_原型

    原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有"prototype"属性,函数对象有"prototype"属性,原型对象有&q ...

  8. ubuntu 加载新硬盘或分区

    查看目前挂载情况 df -lh 查看新的空间或硬盘 fdisk -lu 新硬盘分区 fdisk /dev/sda 输入m 根据提示输入n(创建一个分区) 然后输入e(扩展分区) 输入分区数1 然后指定 ...

  9. arm_GPIO_简单编程例题

    题目 分析下面的汇编led.s,查看S5PV210手册,说明程序的功能,和最终的运行结果,以及相关的硬件原理图,S5PV210手册可以在教学资源里的学习资料文件夹中下载. .equ   GPH3CON ...

  10. View & Controller 一些方法的执行顺序

    一.   加载视图 init-初始化程序 viewDidLoad-加载视图 viewWillAppear-UIViewController对象的视图即将加入窗口时调用: viewDidApper-UI ...