代码之家  ›  专栏  ›  技术社区  ›  Tom H

SQL版本控制方法

  •  13
  • Tom H  · 技术社区  · 14 年前

    关于SQL的版本控制和web上的大量资源有几个问题,但是我找不到完全涵盖我正在做的工作的内容。

    首先,我说的是一种方法论。我熟悉各种源代码管理应用程序,熟悉诸如redgate的SQL Compare等工具,并且知道如何编写一个应用程序来自动检查源代码管理系统的进出。如果有一个工具在提供一个全新的方法论方面特别有用,或者有一个有用的和不寻常的功能,那就太好了,但是对于上面提到的任务,我已经准备好了。

    • 用于对较大表进行数据修复的DML脚本进行了版本控制
    • 服务器可以从版本N升级到版本N+X,其中X可能并不总是1
    • 代码在版本控制系统中不重复—例如,如果我向表中添加一列,我不想确保更改同时在create脚本和alter脚本中
    • 系统需要支持多个客户机,这些客户机的应用程序版本各不相同(尝试在1或2个版本内将它们全部升级,但尚未升级)

    有些组织在其版本控制中保留增量更改脚本,要从版本N到N+3,必须运行N->的脚本;N+1然后N+1->N+2然后N+2->N+3。这些脚本中的一些可能是重复的(例如,添加了一个列,但随后更改了它以更改数据类型)。我们试图避免这种重复性,因为一些客户机数据库可能非常大,所以这些更改可能需要更长的时间。

    有些组织只需在每个版本级别保留一个完整的数据库构建脚本,然后使用类似SQL Compare的工具将数据库升级到这些版本之一。这里的问题是混合DML脚本可能是个问题。设想一个场景,我添加一个列,使用DML脚本填充该列,然后在以后的版本中更改该列的名称。

    也许有一些混合解决方案?也许我只是要求太多了?任何意见或建议将不胜感激。

    谢谢!

    6 回复  |  直到 14 年前
        1
  •  7
  •   Chris    14 年前

    我为此奋斗了好几年,最近才采取了一种似乎效果不错的策略。我生活的要点:

    • 数据库不需要独立于应用程序进行版本控制

    当然,这种方法确实对数据库设计提出了一些要求:

    • 所有的模式更改都是通过脚本完成的-没有GUI工作。
    • 必须特别注意确保所有键、约束等。。命名,以便在必要时由以后的更新脚本引用。
    • 所有更新脚本都应检查现有条件。

    最近一个项目的例子:

    if object_id(N'dbo.Registrations') is null 
    begin
        create table dbo.Registrations
        (
            [Id]                    uniqueidentifier not null,
            [SourceA]               nvarchar(50)     null,
            [SourceB]               nvarchar(50)     null,
            [Title]                 nvarchar(50)     not null,
            [Occupation]            nvarchar(50)     not null,
            [EmailAddress]          nvarchar(100)    not null,
            [FirstName]             nvarchar(50)     not null,
            [LastName]              nvarchar(50)     not null,
            [ClinicName]            nvarchar(200)    not null,
            [ClinicAddress]         nvarchar(50)     not null,
            [ClinicCity]            nvarchar(50)     not null,
            [ClinicState]           nchar(2)         not null,
            [ClinicPostal]          nvarchar(10)     not null,
            [ClinicPhoneNumber]     nvarchar(10)     not null,
            [ClinicPhoneExtension]  nvarchar(10)     not null,
            [ClinicFaxNumber]       nvarchar(10)     not null,
            [NumberOfVets]          int              not null,  
            [IpAddress]             nvarchar(20)     not null,
            [MailOptIn]             bit              not null,
            [EmailOptIn]            bit              not null,
            [Created]               datetime         not null,
            [Modified]              datetime         not null,
            [Deleted]               datetime         null
        );
    end
    
    if not exists(select 1 from information_schema.table_constraints where constraint_name = 'pk_registrations')
        alter table dbo.Registrations add
            constraint pk_registrations primary key nonclustered (Id);
    
    if not exists (select 1 from sysindexes where [name] = 'ix_registrations_created')
        create clustered index ix_registrations_created
            on dbo.Registrations(Created);
    
    if not exists (select 1 from sysindexes where [name] = 'ix_registrations_email')
        create index ix_registrations_email
            on dbo.Registrations(EmailAddress);
    
    if not exists (select 1 from sysindexes where [name] = 'ix_registrations_email')
        create index ix_registrations_name_and_clinic
            on dbo.Registrations (FirstName,
                                  LastName,
                                  ClinicName);
    

    /**********************************************************************
      The original schema allowed null for these columns, but we don't want
      that, so update existing nulls and change the columns to disallow 
      null values
     *********************************************************************/
    
    update dbo.Registrations set SourceA = '' where SourceA is null;
    update dbo.Registrations set SourceB = '' where SourceB is null;
    alter table dbo.Registrations alter column SourceA nvarchar(50) not null;
    alter table dbo.Registrations alter column SourceB nvarchar(50) not null;
    
    /**********************************************************************
      The client wanted to modify the signup form to include a fax opt-in
     *********************************************************************/
    
    if not exists 
    (
        select 1 
          from information_schema.columns
         where table_schema = 'dbo'
           and table_name   = 'Registrations'
           and column_name  = 'FaxOptIn'
    )
    alter table dbo.Registrations 
        add FaxOptIn bit null 
            constraint df_registrations_faxoptin default 0;
    

    003.sql、004.sql等。。。

    在任何给定的时间,我都可以在任何状态下对数据库运行整个系列的脚本,并且知道在当前版本的应用程序中,情况会立即得到改善。因为所有的东西都是脚本化的,所以构建一个简单的安装程序来实现这一点要容易得多,而且将模式更改添加到源代码管理中完全没有问题。

        3
  •  2
  •   Rais Alam    11 年前

    是的,你要求的太多了,但都是非常中肯的观点!在redgate,我们正在使用SQL源代码管理SSMS扩展实现一个完整的数据库开发解决方案,我们也面临着类似的挑战。

    http://www.red-gate.com/products/SQL_Source_Control/index.htm

    目前还没有简单解决方案的最具挑战性的需求是版本管理和部署,您可以非常清楚地描述它。如果您对模式和数据进行了复杂的更改,那么构建一个手工构建的迁移脚本以在两个相邻的版本之间进行迁移可能是不可避免的,因为并非所有的“意图”总是与较新的版本一起保存。列重命名就是一个很好的例子。解决方案可以是设计一个保存意图的系统,或者如果这太复杂,允许用户提供一个自定义脚本来执行复杂的更改。某种版本管理框架将管理这些,并“神奇地”从两个任意版本构建部署脚本。

        4
  •  1
  •   Pranay Rana    14 年前

    对于此类问题,请使用 Visual studio团队系统2008

    在tsf中没有像avialbe这样的特征

    • 数据比较
    • 方案比较
    • 版本控制

    关于数据库版本控制: http://www.codinghorror.com/blog/2006/12/is-your-database-under-version-control.html 更多详细检查: http://msdn.microsoft.com/en-us/library/ms364062(VS.80).aspx

        5
  •  1
  •   SQLDev    14 年前

    以下是SQL审查员方法的描述: How to get your database under version control

        6
  •  0
  •   blorkfish    14 年前

    试试DBSourceTools( http://dbsourcetools.codeplex.com


    此外,您还可以压缩结果以供分发。
    我们使用它对数据库进行源代码控制,并测试新版本的更新补丁。
    在后端,它是围绕SMO构建的,因此支持SQL2000、2005和2008。
    DBDiff是集成的,允许进行模式比较。
    -内森。