回答

收藏

如何按月对表进行分区(“年”和“月”)并自动创建月度分区?

技术问答 技术问答 216 人阅读 | 0 人回复 | 2023-09-14

我正在尝试按
0 M( {- p! ^" ?6 G对表进行分区。我将通过其划分分区的列是具有ISO格式(‘20150110’,20150202’等)的日期时间类型列。
8 l. F/ x* b. p8 z$ D) c例如,我有2010年,2011年和2012年的销售数据。我希望数据按年份进行分区,并且每年也按月份进行分区。(2010/01,2010/02,…8 D  k! V/ s  s1 S+ e9 O* {7 K4 d$ c  x
2010/12,2011/01,… 2015/01 …)5 ?0 Z% q) ^" c: R4 U0 x& Z" V# p0 l
前任:  N! {6 I# \$ \# `0 `1 _
Sales2010Jan,Sales2010Feb,Sales2011Jan,Sales2011Feb,Sales2012Dec等2 A4 o3 R7 x) _* a8 z# Z
我的问题是:有可能吗?如果是,我如何使用SSIS自动执行该过程?
" E5 s* o( ^6 p0 Y2 m                . Z+ ?( p) f, q5 @2 E% k; I. v6 L% H
解决方案:- S1 ?; n( w6 y" |; d' ]" w: S
                + A% ]1 J; B7 F- f7 v

2 {* |, M+ s5 w
; l. h" e6 A$ D                SSIS是一个ETL(提取,转换,加载)。这不是您想要做的。您只需要动态创建DDL语句。0 Q, _- g2 e: K9 t- L/ l# G3 W* o
我在以下季度工作,但如果需要,它也可以在1、2或X个月使用。. }$ ?. c9 S) n( m9 `

0 `3 J  ?7 q. }' H6 a$ f4 S如果要对表进行分区,则首先需要创建文件,文件组和分区表并手动设置分区
% N; I* s2 w- D( ^  y7 ]: g: X5 P& i5 l0 Y4 g
在具有int标识PK和datetime2分区列的表上为2015 Q1(在Q1之前和Q2之后)创建N +8 r# L/ d8 L6 W* i7 P
1分区。更新它以增加月份,使其每月或任何您需要的…1 c! N9 x$ l5 S3 B
( G: c0 [3 K9 U" }* ?2 f/ U$ r
首先创建N个文件组:
1 @* q% _# G$ n: }+ W2 tAlter Database [Test] Add Filegroup [Part_Before2015]' L4 d3 \) _; d+ H: K: D* o9 \
Go
: V1 F8 c/ W  U9 e& T9 kAlter Database Test Add Filegroup [Part_201501]0 R/ ^3 J6 f* e: g
Go" W  @! K1 p& _% \; E% Z
Alter Database Test Add Filegroup [Part_201504]. M; h5 M* A3 M
Go
/ U" T9 D! u6 Q, s; s
( S( L* H  N- E4 l为每个文件组添加一个文件:) T8 q1 p! _: y1 j! s
Alter Database [Test] Add FILE ( NAME = N'Part_Before2015', FILENAME = N'...\Part_Before2015.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ) TO Filegroup [Part_Before2015]) U% J% y- B) t5 U( e
Alter Database [Test] Add FILE ( NAME = N’Part_201501’, FILENAME = N’…\Part_201501.ndf’ , SIZE = 5120KB , FILEGROWTH = 1024KB ) TO Filegroup [Part_201501]
- W. o3 Y7 _3 ?" n& r1 ^4 C+ JAlter Database [Test] Add FILE ( NAME = N’Part_201504’, FILENAME = N’…\Part_201504.ndf’ , SIZE = 5120KB , FILEGROWTH = 1024KB ) TO Filegroup [Part_201504]
8 \/ \1 M* l( d$ s+ Q. [5 s. V% B! \! K$ P8 q& u
在datetime2类型(或日期或什至日期时间)上创建分区函数:) q1 @0 A  d! J; j- O9 O1 |
Create Partition Function RangePartFunction (datetime2)
# b( R7 O, D( z  @4 A8 xas Range Right For Values (‘20150101’, ‘20150401’)
. X( P) n$ O, j2 J3 i- \3 Z0 B: v; L; Y. E, z0 j* @
在每个文件组(N + 1)上使用分区功能创建一个分区方案:% x' H; u. U; q: s
Create Partition Scheme RangePartScheme as Partition RangePartFunction& i/ K  p5 M! R' T9 d
To ([Part_Before2015], [Part_201501], [Part_201504])6 N6 u0 d, V* J
8 Z* i1 i6 ^6 u  K$ j8 x( p
根据其分区方案创建分区表:( }# _1 k1 L; R! }  ^9 }2 a/ w
Create TABLE [PartitionTable] (id int identity(0, 1) not null, date datetime2 not null, text char(8000))- r7 ]8 {4 g/ [. F4 n/ ~
On RangePartScheme (date) ;! A! E3 k& _, v4 h, T% C

; L' O5 ~& z: [, Z在分区列和分区方案上添加聚簇索引:
. p  h: p3 d3 L4 o+ cCreate Clustered Index IDX_Part On dbo.PartitionTable(date)
% H4 E& G4 _) {$ ]On RangePartScheme (date);
) ?% e4 |8 c9 O  Z: G% y& u7 ?' ~0 N* {
将PK添加到id列:+ c2 k) V, G- S+ G$ \. b
Alter Table dbo.PartitionTable Add COntraint PK_Part Primary Key Nonclustered(id, date);7 s# X; H4 o. \0 B

! p, X1 T, B' p8 R3 n" L
" y, K2 }! w9 N+ x+ h, f+ p
构建用于在右边界后添加额外文件组的查询,并拆分最后一个分区
+ R' J% X8 V+ x4 W0 u2 c8 Z/ J, H9 ?: S2 G
查看分区方案扩展和分区功能拆分
1 k/ Q# X. |7 t" Q. P' G查看使用的DMV
% Z8 f: W  s& J
0 h  h. k% ?0 ]) @9 a  ]3 n6 p复习所有这些内容以及如何使用它来创建动态SQL
7 Y/ f. }0 E1 y8 i2 O3 aDeclare @currentDate datetime2" g' }  p' m" B( k0 I" f8 W
Declare @endDate datetime2 = ‘20160701’ – new end date/ c7 i: L& }  q. T" ]$ r; l
Declare @dateAdd int = 3 – Add 3 month = 1 Quarter
9 ~+ o; V! |, s+ i! n0 t  Q9 a– Get Current boundaries
7 m& S, w( \& A3 tSelect @currentDate = DATEADD(MONTH, @dateAdd,Cast(MAX(value) as datetime2)) From sys.partition_range_values as r6 m8 u# @8 a' y9 P' f
    Inner Join sys.partition_functions as f on r.function_id = f.function_id
- e6 r( m& ^% q! h( RWhere f.name = ‘RangePartFunction’
) }! V5 h, A6 V( ]. m$ y– Get all quarters between max and end date
. D  e' a# k1 W) v" b; with d(id, date, name) as (
7 L* [+ v; D! A  r1 W5 W  l8 n: o    Select 0, @currentDate, Convert(char(6), @currentDate, 112)  q+ W1 J9 H! W3 P
    Union All' X! e! g/ F  S/ z
    Select id+1, DATEADD(MONTH, @dateAdd, date), Convert(char(6), DATEADD(MONTH, @dateAdd, date), 112)# X5 Q+ k1 \4 m! A$ B9 A
    From d Where d.date 10, query = ‘If Not Exists(Select 1 From sys.filegroups Where name = ‘’Part_’+name+’‘’)
1 ^; j) m+ \, ~1 `4 i( u        Begin
) X2 y# C9 H. B/ R            Print ‘’Create Filegroup [Part_’+name+’]’‘
7 y+ R# ^8 S+ a+ }8 j2 I$ J& G            Alter Database [Test] Add Filegroup [Part_’+name+’]
2 m" W5 ^" [- M1 w- I' `2 K        End
9 r. \2 r$ D) F% h$ T$ N        GO’5 a1 f% K! W6 k: q/ m6 Z
    From d
- n7 @0 j) U/ K* S    Union All0 S, X4 b: @4 f9 P. c
    Select id10+1, ‘If Not Exists(Select 1 From sys.sysfiles Where name = ‘’Part_’+name+’‘’)$ H% X4 n6 Q5 ~7 i8 ?: E3 i
        Begin $ \3 i& t! Z- L  B% |
            Print ‘’Create File [Part_’+name+’.ndf]’‘+ y# U# }7 E( ?8 k4 ?) E7 \8 J
            Alter Database [Test] Add FILE ( NAME = N’‘Part_’+name+’‘’, FILENAME = N’‘C:\DB\MSSQL11.MSSQLSERVER\MSSQL\DATA\Part_’+name+’.ndf’‘ , SIZE = 5120KB , FILEGROWTH = 1024KB ) TO Filegroup [Part_’+name+’]2 x/ E) {( O8 ~
        End
5 _" E, F# D0 o7 m8 h$ ?        GO’3 |) z7 e+ L' `, e
    From d
) T  r4 `5 L1 W0 k    Union All
, v  H( X+ Z5 }% m. m; I% V5 h& e    Select id10+2, ‘Print ‘’Add Range [Part_’+name+’]’‘
7 g( f# S  `* b3 G0 L        Alter Partition Scheme RangePartScheme Next Used [Part_’+name+’]1 F9 `6 v1 K+ h
        Go’) _/ r1 X! A0 O6 p4 z% T- G
    From d' J! m6 H. v5 G% F5 o, E
    Union All
% Y6 {) _0 ]& |1 d+ Q    Select id10+3, ‘Print ‘’Split Function [‘+Convert(char(8), date, 112)+’]’‘
6 L! q# M" g3 p        Alter Partition Function RangePartFunction() Split Range (‘’‘+Convert(char(8), date, 112)+’‘’);
% d* p. F1 n$ t3 A4 ?1 o        Go’7 m+ J% j4 I5 _
    From d+ |9 J8 N$ d2 ^9 V
) as q order by id, F) f3 V. c& {% T0 z7 W9 h

5 k/ k' i, F0 P: T* D+ J- x

  n9 y( i$ P6 S该查询的输出是必须按顺序运行的SQL查询的列表。
7 g+ h6 u+ W9 Z1 Y  I3 k) p+ q0 G3 Y
执行动态SQL. W, y- U; X! m5 j; P# z1 P

$ @& |- q9 p6 G, L可以手动执行(SSMS中的复制和过往操作)
6 G  |$ |# Z( l+ d3 Z它可以在while循环中执行,也可以使用游标执行,游标将逐一执行输出表的每一行(使用sp_executesql)
% o4 U& m2 g8 N% O1 [

8 I) K% \* f4 q. m自动化/ W2 S) f& e7 u
" I3 m. E  p+ q( Z) Q. ^
创建一个执行SQL查询的SQL Server作业:运行用于创建动态SQL的查询,将其输出保存到表变量中,然后使用循环/游标执行每个语句
  P& e+ C6 E/ E. I9 x: ~# q
+ {- h* W# y1 c3 p3 [2 {) G
如果要每月运行一次并确保始终创建接下来的12个月,请使用此命令 Set @endDate = DATEADD(MONTH, 12, getdate())
1 u7 ~5 d* U& H/ Z  a% ~: ]! |$ @7 K% v7 d2 T8 G! q
最后% b" o( O, u/ I, g
0 J* H; f; v5 c& M, i6 ^( u

' I+ o4 h( n& e6 T/ C它将为函数的最后一个边界和@endDate之间的N个丢失的四分之一输出4 * N行:
9 x+ O1 D' V( E- U; Z& |创建文件组
+ G5 y# x, k+ H: ~2 m2 v- U- {在文件组上创建文件
$ ]9 n1 q4 u( R  w3 h3 t7 R6 v扩展分区方案的范围
  q6 S( b. |+ Q1 W/ M0 A分割分区功能的范围
+ a( t1 f5 h: A您可以使用光标或while循环逐行运行它,也可以将其复制并粘贴到SMSS中。
% K4 f* F) J6 p/ Q. S' n

1 ]4 {3 ^; r& b) a5 I它也可以通过工作自动化,即。@endDate = DATEADD(MONTH, 3, getdate()将在接下来的3个月内创建/ k5 T( ?+ d7 C7 C% o" j7 S  Q
如果要每月分区,请将@dateAdd更改为11 o2 N( r+ s/ w4 E. z. P
添加您自己的列或检查+ y. _/ S$ b7 `1 N% m

6 [6 k. _6 b$ O7 Z+ t. n- a9 u4 M; H关联' }# V, m$ c* g6 ~
1 V) ^5 t* L$ B  Y# `2 Z7 n6 o
创建作业= https://www.mssqltips.com/sqlservertip/3052/simple-way-to-create-a-sql-
: U3 q! k$ w% C$ U& D  s; Jserver-job-using-tsql/
6 u3 z, l4 u6 t; ]# Y8 `2 y9 [sp_executesql = https://technet.microsoft.com/zh-
; }6 _: E- b' ecn/library/ms188001%28v=sql.110%29.aspx/ o9 S. l, z$ Y% H
While循环= https://dba.stackexchange.com/questions/57933/can-exec-work-with-+ q& x& a9 @4 e$ R) L
while-loop-of-cursor
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则