|
关于SO的SQL版本控制和网络上的大量资源,SO上存在几个问题,但是我找不到能够完全覆盖我要尝试做的事情。
! ^0 D0 `0 h3 E* ]首先,我在这里谈论一种方法。我熟悉各种源代码控制应用程序,也熟悉Red Gate的SQL
5 b& Z" V0 c1 Z8 h5 H7 vCompare等工具,并且我知道如何编写应用程序以自动检查和检查源代码控制系统中的内容。如果有一种工具对于提供一种全新的方法特别有用,或者具有有用的和罕见的功能,那就太好了,但是对于上面提到的任务,我已经设定好了。( g8 O( g) L" f7 h a% X
我要满足的要求是:
& \) Y+ w4 I1 B9 {" \数据库模式和查找表数据已版本化) \* D% u$ u: W" B" z4 }4 \2 }8 F
对用于较大表的数据修复的DML脚本进行了版本控制+ S3 p6 e* L1 {0 x& k; `
可以将服务器从版本N升级到版本N + X,其中X不一定总是1
8 K8 o4 }$ \/ M' v代码在版本控制系统中没有重复-例如,如果我在表中添加一列,则不必确保更改同时在创建脚本和更改脚本中进行
8 F" ~5 v) h& ?, ?7 O/ f* `系统需要支持具有不同版本的应用程序的多个客户端(试图将它们全部升级到1或2个发行版之内,但尚未发行)' c8 Y( w) R9 n+ ~4 z2 P/ Z% j
& ~$ Z3 M3 ?0 V. ]2 S5 @) d& [
一些组织将增量更改脚本保留在其版本控制中,并且要从版本N升级到N + 3,您必须为N-> N + 1然后N + 1-> N + 2然后N + 2-> N6 ]) H$ J+ c& w3 C+ |( E5 Y
+运行脚本3。这些脚本中的某些脚本可能是重复的(例如,添加了列,但随后又对其进行了更改以更改数据类型)。由于某些客户端DB可能非常大,因此我们试图避免这种重复,因此这些更改可能会花费比必要时间更长的时间。
, u: [) n% h0 c- [) \4 B" o x% A一些组织将仅在每个版本级别保留完整的数据库构建脚本,然后使用SQL% U1 Q$ v: _! z2 W
Compare之类的工具将数据库升级到其中一个版本。这里的问题是,混合DML脚本可能是一个问题。想象一下一个场景,我添加一列,使用DML脚本填充该列,然后在更高版本中更改该列名。
; T* ]; W7 \2 i9 {# y% T也许有一些混合解决方案?也许我只是要求太多?任何想法或建议,将不胜感激。
! E: e$ l3 g+ w. m1 G" d1 i$ h& A如果主持人认为这更适合作为社区Wiki,请告诉我。
& ?6 y2 h, Q+ L- B. U谢谢!+ ^2 H6 @' Y w
2 f2 Y: Z) a d3 J* o/ s' a解决方案:, j7 ]4 ?+ m9 {% O7 d
( k: ^, Q$ Y6 s0 i9 t) Q" R7 \! K# f, d) n3 W& `! ~' l/ m# X
6 a( H) E8 }# Y h0 b' d
我为此苦苦挣扎了几年,最近才采取了一项效果很好的策略。我生活的重点:2 v8 E/ \& N; U
无需从应用程序独立对数据库进行版本控制+ m+ w4 g7 }) f' X A
所有数据库更新脚本均应幂等
9 n# P. x* s/ B9 i; |- X: @
' |' }9 _" N# d: A& s& {) v- p结果,我不再创建任何类型的版本表。我只是将更改添加到编号的.sql文件序列中,这些更改可以在任何给定时间应用而不会破坏数据库。如果使事情变得容易,我将为该应用程序编写一个简单的安装程序屏幕,以允许管理员在需要时运行这些脚本。! m) X- [! H+ c- z! R+ @4 b1 N9 |
当然,此方法确实对数据库设计有一些要求:" X4 P. Z$ i1 k7 {
所有架构更改均通过脚本完成-无需GUI工作。3 o' ]" l6 q9 ?. ]1 x: H. h
必须格外小心,以确保所有键,约束等都被命名,以便以后如有必要,可以在以后的更新脚本中引用它们。1 O( t# O: _& K, F6 _4 A3 {
所有更新脚本都应检查现有条件。8 v+ q* Z1 T+ r- e- p
$ H& D! n/ Q1 A+ ~/ f: S- ~来自最近项目的示例:) |$ G+ _4 y' n$ s" ~& ?- H3 w
001.sql:9 s' O; w1 y: d+ c: v
if object_id(N'dbo.Registrations') is null
! C0 o" Q* G! o+ C+ d* c8 tbegin% W2 l$ l3 I! F
create table dbo.Registrations
5 R& _4 E1 n9 t" m* p3 X4 I' Z! C (5 o; _3 J! C5 @
[Id] uniqueidentifier not null,/ H. u+ E7 g1 }& X8 k \! n3 g
[SourceA] nvarchar(50) null,
3 R! ?8 ^+ [; }5 }4 x7 V [SourceB] nvarchar(50) null,0 Q8 _ m9 A& E% I8 z
[Title] nvarchar(50) not null,0 C$ ~6 }! r* I& M8 }# I
[Occupation] nvarchar(50) not null,
* ~6 W9 n& s" [2 e [EmailAddress] nvarchar(100) not null,
7 y" I" m4 L3 A! |- n8 T9 t6 K. e) | [FirstName] nvarchar(50) not null,3 X2 y) X U( _
[LastName] nvarchar(50) not null," O6 |- H7 ~( ?* ^0 ]
[ClinicName] nvarchar(200) not null,
0 {8 {* W% k3 T; Z& V$ y$ e$ T [ClinicAddress] nvarchar(50) not null,5 D M$ u+ z# I- l% [ Y
[ClinicCity] nvarchar(50) not null,
4 x( I: }: Z" x) Q' A: i1 ~ [ClinicState] nchar(2) not null,
6 {( I! M( D, o5 s' t [ClinicPostal] nvarchar(10) not null,
6 S; A; Q) w* s [ClinicPhoneNumber] nvarchar(10) not null,& F3 k! M5 b- t* E' F8 w
[ClinicPhoneExtension] nvarchar(10) not null,; Y! S! k0 x" r0 R. \* E3 s6 P
[ClinicFaxNumber] nvarchar(10) not null,4 [ |' w6 d) V# d. n1 r2 V
[NumberOfVets] int not null, & e2 v1 j' @ z6 ^& q% n& s
[IpAddress] nvarchar(20) not null,. _7 X( l8 A; v6 X
[MailOptIn] bit not null,
# u5 d; D8 P$ U2 s [EmailOptIn] bit not null,
* j1 o- j! I \! f4 ]4 q) [0 ` [Created] datetime not null,( Y) i' U7 @& n8 q' {9 @4 C* d+ d& A( B
[Modified] datetime not null,
* z- y% }* U/ C3 y9 N" J/ S [Deleted] datetime null
1 S; m& ?+ ]- j1 M$ A) E4 j );
4 N/ I. b8 y" W2 }3 J$ ~end6 C0 ~, Y, F# E3 n
if not exists(select 1 from information_schema.table_constraints where constraint_name = 'pk_registrations')
6 p- y; ~1 T6 y6 F" V alter table dbo.Registrations add
' H, n+ W( H, [0 A, d& f2 _& ^# `# X constraint pk_registrations primary key nonclustered (Id);" e4 [+ A/ f' p1 p/ L5 w1 \+ A
if not exists (select 1 from sysindexes where [name] = 'ix_registrations_created')( c& a0 a9 s% u
create clustered index ix_registrations_created! O3 c6 ^* v9 ]' q
on dbo.Registrations(Created);# j4 y% y/ X! X2 M
if not exists (select 1 from sysindexes where [name] = 'ix_registrations_email')
' V0 P& r4 H, S: y0 b7 b" ? create index ix_registrations_email& D- Z9 j( |4 i
on dbo.Registrations(EmailAddress);; {# E e2 f6 P' E1 U2 j
if not exists (select 1 from sysindexes where [name] = 'ix_registrations_email')
$ C- V" a# Y* p0 e: M8 { create index ix_registrations_name_and_clinic7 b+ t, m$ t! \* }! p% W3 K1 O; `
on dbo.Registrations (FirstName,
: E+ P8 S8 E1 G* p7 N) Z! @ LastName,
, } \. ^8 t& A( o7 z" u1 d! R ClinicName);! A2 i" R; d* \& |: x J
002.sql' a3 ] V R u- S o
/**********************************************************************. }" K3 Z# g5 |8 ]0 w
The original schema allowed null for these columns, but we don't want
; v3 c2 |( _; z" Y that, so update existing nulls and change the columns to disallow % A) m `3 M2 |: @( a: C$ e
null values
[" h( X. j; G6 k" R1 i1 y+ @0 H3 f& I *********************************************************************/$ c) o. h" d9 C9 C9 ]4 r; r* p
update dbo.Registrations set SourceA = '' where SourceA is null;$ ^ n( s% J8 T( q9 t
update dbo.Registrations set SourceB = '' where SourceB is null;# p; `, M- q5 o3 k5 ?& i
alter table dbo.Registrations alter column SourceA nvarchar(50) not null;/ O" j5 q" j Z; D) ]9 @8 i
alter table dbo.Registrations alter column SourceB nvarchar(50) not null;5 w: K5 ?1 k1 ?: m' |1 Z r8 I; Y* M" `
/**********************************************************************
0 \% c" L* V5 ?: o1 Y The client wanted to modify the signup form to include a fax opt-in
/ q9 C# S$ H% K( d2 Q4 ?# e* y *********************************************************************/
& Y! Z6 c2 b ?if not exists , M0 _7 l! w: N2 x0 e5 ?# z! X
(
9 z5 a; ?+ ^6 P$ f. j9 L select 1
. D+ E" y [$ J( y2 Y6 f' u# Q; y from information_schema.columns
2 ^ j$ p8 F# w- F/ ] where table_schema = 'dbo'. B# `% j- D1 t% R( a( g# R
and table_name = 'Registrations'$ Q4 a) F& n( v% p: m+ f
and column_name = 'FaxOptIn'
/ C4 F q' W5 p. [)
( H3 D0 R- J: k malter table dbo.Registrations
1 W* l! d8 @' y/ s9 l add FaxOptIn bit null
# O$ h/ ~6 ^0 k0 v2 O- s constraint df_registrations_faxoptin default 0;
. }" [% u% k4 T8 z, W) |003.sql,004.sql等…3 T* k" ], P& w; B0 Q
在任何给定的时间,我都可以在任何状态下对数据库运行整个脚本系列,并且知道可以立即使用当前版本的应用程序来加快运行速度。因为所有内容都是脚本编写的,所以构建一个简单的安装程序来执行此操作要容易得多,并且将模式更改添加到源代码管理中完全没有问题。 |
|