SQL Server 动态生成分区脚本

一、前言

前段时间使用表分区比较多,虽然已经写了SQL Server 合并(删除)分区解惑SQL Server 2005 分区模板与实例,但是在实践中一直感觉修改SQL脚本的时间比较多,一直想抽个时间来把分区脚本进行动态化,今天终于付之于行动了。需要说明的一点,下面的脚本并不能满足所有情况,用户可以根据自己的需要进行相应的调整,应该可以满足你的需求的。

在SQL Server 2005中只能通过SQL脚本来创建表分区,而在SQL Server 2008的SSMS中已经提供了操作界面进行表分区,但是也不能把操作生成SQL脚本,所以,下面的SQL的应用场景包括SQL Server 2005、SQL Server 2008。

 

二、分解

下面就是生成分区的脚本了,在执行之前,你需要填写数据库名称、表名、分区表字段、需要的分区数、保存分区文件的路径、分区初始化大小、分区文件的增量、分区边界值;

这里的分区边界值是按照int类型进行增量计算的,比如你想以每100W进行范围分区的话,那你只要设置@FunValue为100W;如果你的分区边界值是其它类型值或者是不等范围的分区,那么你只要修改这个变量为字符串,并对分区函数的生成代码进行相应修改就可以满足你的需求了。

通常情况下,我们会以一个表Id(int),并且是自增作为分区字段,这样就很容易区分历史数据了,而且对分区的操作隔离也是最明显的。

--生成分区脚本
DECLARE @DataBaseName NVARCHAR(50)--数据库名称
DECLARE @TableName NVARCHAR(50)--表名称
DECLARE @ColumnName NVARCHAR(50)--字段名称
DECLARE @PartNumber INT--需要分多少个区
DECLARE @Location NVARCHAR(50)--保存分区文件的路径
DECLARE @Size NVARCHAR(50)--分区初始化大小
DECLARE @FileGrowth NVARCHAR(50)--分区文件增量
DECLARE @FunValue INT--分区分段值
DECLARE @i INT
DECLARE @PartNumberStr NVARCHAR(50)
DECLARE @sql NVARCHAR(max)

--设置下面变量
SET @DataBaseName = 'MyDataBase'
SET @TableName = 'User'
SET @ColumnName = 'Id'
SET @PartNumber = 4
SET @Location = 'E:\DataBase\'
SET @Size = '30MB'
SET @FileGrowth = '10%'
SET @FunValue = 10000000

--1.创建文件组
SET @i = 1
PRINT '--1.创建文件组'
WHILE @i <= @PartNumber
BEGIN
    SET @PartNumberStr =  RIGHT('0' + CONVERT(NVARCHAR,@i),2)
    SET @sql = 'ALTER DATABASE ['+@DataBaseName +']
ADD FILEGROUP [FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+']'
    PRINT @sql + CHAR(13)
    SET @i=@i+1
END

--2.创建文件
SET @i = 1
PRINT CHAR(13)+'--2.创建文件'
WHILE @i <= @PartNumber
BEGIN
    SET @PartNumberStr =  RIGHT('0' + CONVERT(NVARCHAR,@i),2)
    SET @sql = 'ALTER DATABASE ['+@DataBaseName +']
ADD FILE
(NAME = N''FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+'_data'',FILENAME = N'''+@Location+'FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+'_data.ndf'',SIZE = '+@Size+', FILEGROWTH = '+@FileGrowth+' )
TO FILEGROUP [FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+'];'
    PRINT @sql + CHAR(13)
    SET @i=@i+1
END

--3.创建分区函数
PRINT CHAR(13)+'--3.创建分区函数'
DECLARE @FunValueStr NVARCHAR(MAX) 
SET @i = 1
SET @FunValueStr = ''
WHILE @i < @PartNumber
BEGIN
    SET @FunValueStr = @FunValueStr + convert(NVARCHAR(50),(@i*@FunValue)) + ','
    SET @i=@i+1
END
SET @FunValueStr = substring(@FunValueStr,1,len(@FunValueStr)-1)
SET @sql = 'CREATE PARTITION FUNCTION
Fun_'+@TableName+'_'+@ColumnName+'(INT) AS
RANGE RIGHT
FOR VALUES('+@FunValueStr+')'
PRINT @sql + CHAR(13)

--4.创建分区方案
PRINT CHAR(13)+'--4.创建分区方案'
DECLARE @FileGroupStr NVARCHAR(MAX) 
SET @i = 1
SET @FileGroupStr = ''
WHILE @i <= @PartNumber
BEGIN
    SET @PartNumberStr =  RIGHT('0' + CONVERT(NVARCHAR,@i),2)
    SET @FileGroupStr = @FileGroupStr + '[FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+'],'
    SET @i=@i+1
END
SET @FileGroupStr = substring(@FileGroupStr,1,len(@FileGroupStr)-1)
SET @sql = 'CREATE PARTITION SCHEME
Sch_'+@TableName+'_'+@ColumnName+' AS
PARTITION Fun_'+@TableName+'_'+@ColumnName+'
TO('+@FileGroupStr+')'
PRINT @sql + CHAR(13)

--5.分区函数的记录数
PRINT CHAR(13)+'--5.分区函数的记录数'
SET @sql = 'SELECT $PARTITION.Fun_'+@TableName+'_'+@ColumnName+'('+@ColumnName+') AS Partition_num,
  MIN('+@ColumnName+') AS Min_value,MAX('+@ColumnName+') AS Max_value,COUNT(1) AS Record_num
FROM dbo.'+@TableName+'
GROUP BY $PARTITION.Fun_'+@TableName+'_'+@ColumnName+'('+@ColumnName+')
ORDER BY $PARTITION.Fun_'+@TableName+'_'+@ColumnName+'('+@ColumnName+');'
PRINT @sql + CHAR(13)

生成的脚本如下:

--1.创建文件组
ALTER DATABASE [MyDataBase]
ADD FILEGROUP [FG_User_Id_01]

ALTER DATABASE [MyDataBase]
ADD FILEGROUP [FG_User_Id_02]

ALTER DATABASE [MyDataBase]
ADD FILEGROUP [FG_User_Id_03]

ALTER DATABASE [MyDataBase]
ADD FILEGROUP [FG_User_Id_04]

--2.创建文件
ALTER DATABASE [MyDataBase]
ADD FILE
(NAME = N'FG_User_Id_01_data',FILENAME = N'E:\DataBase\FG_User_Id_01_data.ndf',SIZE = 30MB, FILEGROWTH = 10% )
TO FILEGROUP [FG_User_Id_01];

ALTER DATABASE [MyDataBase]
ADD FILE
(NAME = N'FG_User_Id_02_data',FILENAME = N'E:\DataBase\FG_User_Id_02_data.ndf',SIZE = 30MB, FILEGROWTH = 10% )
TO FILEGROUP [FG_User_Id_02];

ALTER DATABASE [MyDataBase]
ADD FILE
(NAME = N'FG_User_Id_03_data',FILENAME = N'E:\DataBase\FG_User_Id_03_data.ndf',SIZE = 30MB, FILEGROWTH = 10% )
TO FILEGROUP [FG_User_Id_03];

ALTER DATABASE [MyDataBase]
ADD FILE
(NAME = N'FG_User_Id_04_data',FILENAME = N'E:\DataBase\FG_User_Id_04_data.ndf',SIZE = 30MB, FILEGROWTH = 10% )
TO FILEGROUP [FG_User_Id_04];

--3.创建分区函数
CREATE PARTITION FUNCTION
Fun_User_Id(INT) AS
RANGE RIGHT
FOR VALUES(10000000,20000000,30000000)

--4.创建分区方案
CREATE PARTITION SCHEME
Sch_User_Id AS
PARTITION Fun_User_Id
TO([FG_User_Id_01],[FG_User_Id_02],[FG_User_Id_03],[FG_User_Id_04])

--5.分区函数的记录数
SELECT $PARTITION.Fun_User_Id(Id) AS Partition_num,
  MIN(Id) AS Min_value,MAX(Id) AS Max_value,COUNT(1) AS Record_num
FROM dbo.User
GROUP BY $PARTITION.Fun_User_Id(Id)
ORDER BY $PARTITION.Fun_User_Id(Id);

三、后记

在MSND的SQL Server 2005 中的分区表和索引中同样提供了一个脚本用于生成表分区,和他不同的是:他采用了表来保存文件路径,再使用游标来创建文件而已,其实这只能生成一部分代码,而我的脚本不同之处就是能最大限度的生成常规表分区的常用代码,方便快捷很多。有兴趣的童鞋可以下载:SQL2005PartitioningScripts.exe

上面使用表保存信息的这种想法在后期的数据搬迁(比如需要对一个现有的表进行表分区,这种情况下通常会先建一个分区表,再进行导入现有表的数据)中是有很大的用处的,后面的文章中会讲讲如何进行自动化的数据搬迁,敬请留意。

时间: 2024-08-20 10:14:20

SQL Server 动态生成分区脚本的相关文章

SQL Server 动态生成数据库所有表Insert语句

一. 背景 SQL Server,如果我们需要把数据库A的所有表数据到数据库B中,通常我们会怎么做呢?我会使用SSMS的导入导出功能,进行表数据的导入导出,无可厚非,这样的导入非常简单和方便: 但是,当我们的表有上百个,而且有些表是有自增ID的,那么这个时候使用SSMS的话,你需要一个个手动设置(如图1),你要知道,需要设置上百个的这些选项是件多么痛苦的事情,而且最后很可能会因为外键约束导致导入导出失败. (图1) 虽然SSMS在导入导出的最后一步提供了生成SSIS包的功能,但是对于转移数据的需

SQL Server 动态行转列(参数化表名、分组列、行转列字段、字段值)

原文:SQL Server 动态行转列(参数化表名.分组列.行转列字段.字段值) 一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes) 方法一:使用拼接SQL,静态列字段: 方法二:使用拼接SQL,动态列字段: 方法三:使用PIVOT关系运算符,静态列字段: 方法四:使用PIVOT关系运算符,动态列字段: 扩展阅读一:参数化表名.分组列.行转列字段.字段值: 扩展阅读二:在前面的基础上加入条件过滤: 参考文献(R

SQL Server 创建表分区

原文:SQL Server 创建表分区 先准备测试表 CREATE TABLE [dbo].[Employee] ( EmployeeNo INT IDENTITY(1,1) PRIMARY KEY, EmployeeName NVARCHAR(50) NULL ); 插入一些数据 INSERT Employee DEFAULT VALUES; GO 10000 UPDATE Employee set EmployeeName = 'Employee ' + CONVERT(VARCHAR, E

SQL Server 清除数据库日志脚本

SQL Server 清除数据库日志脚本 清除mssql数据库日志的代码: Use master go declare @dbname varchar(50) declare temp_cur cursor scroll for select name from sysdatabases open temp_cur fetch first from temp_cur into @dbname while @@fetch_status =0  begin   exec ('backup log [

PowerDesigner 16.5对SQL Server 2012 生成数据库时&quot;不支持扩展属性&quot;问题

原文:PowerDesigner 16.5对SQL Server 2012 生成数据库时"不支持扩展属性"问题 团队合作设计一套系统数据模型,创建了PDM后,Table.View.Store Procedure等都创建好了,且创建了多个Schema方便管理这些数据库对象,但Table.view.Column等对象有Comment时(用来在团队不同成员间共享描述信息) 生成数据库时会得到一个提示"不支持扩展属性,或对象不存在",分析发现异常在类似以下语句: if ex

SQL Server中生成测试数据

原文:SQL Server中生成测试数据 简介      在实际的开发过程中.很多情况下我们都需要在数据库中插入大量测试数据来对程序的功能进行测试.而生成的测试数据往往需要符合特定规则.虽然可以自己写一段程序来进行插入数据,但每一个项目就写一个插入数据的程序并不明智.本文主要介绍使用VS2010的数据生成计划在SQL Server中生成测试数据.   生成测试数据的方法      1.手动编辑           在开发过程中,非常少量的数据可以手动插入.这个方法的缺点可想而知-.插入100条数

双十一数据库也疯狂,SQL Server 无法生成 FRunCM 线程,求解

  双十一抢购才开始,数据库就出问题了! 一身冷汗,注意不是哪个电商的数据库出问题了,是一个客户公司的数据库出问题了!客户公司是一个原材料生成企业,工厂昼夜不停的生产,核心表数据已有千万之多!可是双十一和它根本就没有任何关系,凌晨两点多数据库就挂了,导致工厂车间所有无法生产!   (一) 问题描述 数据库突然在凌晨两点多就停止了服务,然后就不能重启了!每次去启动之后又自动停止服务了 打开日志查看: SQL Server无法生成FRunCM线程,请查看SQL Server日志和Windows日志

sql server自动生成批量执行SQL脚本的批处理

  场景: DBA那边给我导出了所有的存储.函数等等对象的创建脚本,有上千个文件. 现在需要将这些对象创建脚本导入到另外一个库,如何解决呢? 手动一个个执行显然不太现实. 于是手动写了一个批处理,将所有的文件形成一个.SQL的脚本,最后以@生成的.SQL脚本方式导入到目标库中. OS环境:WINDOWS xp 脚本内容如下: @echo off if exist list.sql del list.sql /q :input cls set input=: set /p input= 请输入要进

SQL Server 2005的分区

SQL Server 2005是微软在推出SQL Server 2000后时隔五年推出的一个数据库.相对于SQL Server2000来说有了质的提高.它给我们提供了诸多新特性,例如:复制.分区.动态管理视图.CTE.性能顾问等等. 在微软TechNet上是这样介绍分区表和分区索引的: Instruction 已分区表和已分区索引的数据划分为分布于一个数据库中多个文件组的单元.数据是按水平方式分区的,因此多组行映射到单个的分区.对数据进行查询或更新时,表或索引将被视为单个逻辑实体.单个索引或表的