源代码管理中的存储过程/数据库模式


69

你们是否跟踪所选源代码控制系统中的存储过程和数据库架构?

进行更改时(添加表,更新存储的proc,如何将更改添加到源代码管理中?

我们在工作中使用SQL Server,并且我已经开始使用darcs进行版本控制,但是我对通用策略以及任何方便的工具感到好奇。

编辑:哇,谢谢大家提出的所有宝贵建议!希望我可以选择多个“接受的答案”!


1
提出多个“已接受的答案”一项功能请求;)
Marc Gear

Answers:


43

我们选择编写所有内容的脚本,其中包括所有存储过程和模式更改。不需要所见即所得的工具,也不需要花哨的“同步”程序。

模式更改很容易,您所需要做的就是为该版本创建并维护一个文件,包括所有模式和数据更改。这将成为您从版本x到x + 1的转换脚本。然后,您可以针对生产备份运行它,并将其集成到“每日构建”中,以验证其是否正常运行。请注意,不要更改或删除已编写的架构/数据加载sql,这很重要,因为这样可能会破坏以后编写的所有sql。

-- change #1234
ALTER TABLE asdf ADD COLUMN MyNewID INT
GO

-- change #5678
ALTER TABLE asdf DROP COLUMN SomeOtherID
GO

对于存储过程,我们为每个sproc选择一个文件,并且使用drop / create形式。部署时将重新创建所有存储过程。缺点是,如果在源代码控制之外进行更改,则更改将丢失。同时,任何代码都是如此,但是您的DBA'a需要意识到这一点。这确实阻止了团队之外的人对您的存储过程感到厌烦,因为他们的更改会在升级中丢失。

使用Sql Server时,语法如下所示:

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[usp_MyProc]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [usp_MyProc]
GO

CREATE PROCEDURE [usp_MyProc]
(
    @UserID INT
)
AS

SET NOCOUNT ON

-- stored procedure logic.

SET NOCOUNT OFF

GO  

剩下要做的唯一事情就是编写一个实用程序,该程序可以整理所有单个文件,并使用整个更新集(作为一个脚本)创建一个新文件。为此,首先添加架构更改,然后递归目录结构并包括所有存储过程文件。

作为编写所有脚本的好处,您将在读写SQL方面变得更好。您也可以使整个过程更加复杂,但这是如何在没有任何特殊软件的情况下对所有sql进行源代码控制的基本格式。

附录:Rick是正确的,您将失去使用DROP / CREATE的存储过程的权限,因此您可能需要编写另一个脚本来重新启用特定权限。此权限脚本将是最后运行的脚本。我们的经验发现,ALTER和DROP / CREATE语义之间存在更多问题。青年汽车


嗯 我不希望它是垃圾邮件。抱歉,如果这样做。不,我不同意你的任期。我只是让您知道该技术的改进实现,我认为这与您的答案有关。您的第一句话暗示这些工具在某种程度上几乎是负担,这很好,但这已经是两年前了!我删除了我的评论,因为您认为它令人反感。
David Atkinson

@David我没有发现您的意见令人反感。我只是不想开始与我的答案没有直接关系的评论对话。
罗伯特·保尔森

说到使这个过程更加复杂-我们创建了一个TFS工作项和服务来支持该过程,并添加了一些自动化测试。它位于codeplex上:link
gordy

您可以在CREATE脚本中包含对象权限,例如GRANT [user] EXECUTE ON [whatever] GO。这将不需要维护单独的权限脚本,因为将使用必需的权限来创建每个对象。
Mentatmatt 2014年

@Mentatmatt,您可以。我认为我们当前的过程是每个sql用户只有一个权限文件,我们认为这是最容易管理的。
罗伯特·保尔森

8

在Visual Studio中创建一个“数据库项目”以编写和管理您的sQL代码,并使该项目与解决方案的其余部分一起受版本控制。


在Visual Studio 2008数据库版中
murki 2010年

8

我们在上一份工作中使用的解决方案是在脚本添加到源代码管理时对其编号:

01.CreateUserTable.sql
02.PopulateUserTable
03.AlterUserTable.sql
04.CreateOrderTable.sql

这个想法是,我们总是知道运行脚本的顺序,并且我们可以避免必须管理在尝试修改脚本#1时可能发生的数据完整性问题(这可能会导致#2中的INSERT失败)。


一旦获得100个脚本,文件系统的名称排序就不会得到错误的排序吗?
伊恩·沃伯顿

5

使用SQL Server中的放置/创建脚本要记住的一件事是对象级权限将丢失。我们更改了标准,改为使用ALTER脚本来维护这些权限。

还有其他一些警告,例如删除对象会删除sp_depends使用的依赖项记录,而创建对象只会为该对象创建依赖项。因此,如果删除/创建视图,则sp_depends将不再知道引用该视图的任何对象。

故事的寓意,使用ALTER脚本。


5

我同意(并赞成)罗伯特·保尔森的做法。这就是说,您控制着一支具有责任心和纪律性的开发团队,并遵守这种做法。

为了将其“强加”到我的团队中,我们的解决方案至少维护了Visual Studio Team Edition for Database Professionals的一个数据库项目。与解决方案中的其他项目一样,数据库项目也获得版本控制。将数据库中的所有内容分解为可维护的块,使我的团队“自律”成为自然的开发过程。

当然,作为Visual Studio项目,这绝非完美。您会遇到许多奇怪的问题,这些问题可能会让您感到沮丧或困惑。在完成项目之前,需要对项目的工作原理有一定的了解。例子包括

但是对于没有版本化数据库对象实践的团队来说,这是一个好的开始。当然,另一个著名的替代方案是Red Gate的SQL Server产品套件,大多数使用它们的人都认为它们优于Microsoft的产品。



3

根据我的经验,结合不同的观点。在Oracle世界中,一切都由“创建” DDL脚本管理。如ahockley所述,每个对象都有一个脚本。如果需要更改对象,则修改其DDL脚本。有一个包装器脚本可调用所有对象脚本,以便您可以将当前数据库构建部署到所需的任何环境。这是为主要核心创建的。

显然,在实时应用程序中,每当您推送需要新列的新构建时,就不会删除该表并重新创建它。您将要做一个ALTER脚本并添加该列。因此,每次需要进行此类更改时,总有两件事要做:1)编写alter DDL和2)更新核心创建DDL以反映更改。两者都进入源代码控制,但是单个alter脚本更多地是瞬时时间点更改,因为它仅用于应用增量。

您还可以使用诸如ERWin之类的工具来更新模型并向前生成DDL,但是我知道大多数DBA都不相信使用建模工具以所需的方式生成脚本。您也可以使用ERWin定期将您的核心DDL脚本反向工程为模型,但这要花很多时间才能使它看起来正确(每次执行时都花时间)。

在Microsoft世界中,我们采用了类似的策略,但是我们使用Red Gate产品来帮助管理脚本和增量。仍将脚本置于源代码管理中。每个对象仍然有一个脚本(表,存储过程等)。首先,某些DBA确实更喜欢使用SQL Server GUI来管理对象而不是使用脚本。但是,这使得随着企业的发展而持续地对其进行管理非常困难。

如果DDL在源代码控制中,则使用任何构建工具(通常是ant)编写部署脚本都是很简单的。


1
您是否有机会试用Red Gate的SQL Source Control来管理模式更改?如果没有,请尝试一下,因为我们非常有兴趣获得您的反馈!额外的好处是,如果您仍然是DBA的首选,则可以继续使用SSMS。red-gate.com/products/sql_source_control/index.htm
David Atkinson,2010年

3

我发现到目前为止,最简单,最快和最安全的方法是硬着头皮使用RedGate的SQL Source Control。编写脚本并在几分钟内将其存储在存储库中。我只希望RedGate将产品视为损失领先者,以便可以更广泛地使用它。


2

与上面的Robert Paulson相似,我们的组织将数据库保持在源代码控制之下。但是,我们的不同之处在于,我们尝试限制所拥有的脚本数量。

对于任何新项目,都有固定的过程。我们有版本1的架构创建脚本,存储的proc创建脚本以及可能的初始数据加载创建脚本。所有过程都保存在一个公认的大型文件中。如果使用的是企业库,则包括用于记录的创建脚本的副本;如果它是一个使用ASP.NET应用程序框架(身份验证,个性化等)的ASP.NET项目,则我们还将包括该脚本。(我们从Microsoft的工具中生成了它,然后对其进行了调整,直到它可以在不同站点上以可复制的方式工作。这不是很有趣,但是却是宝贵的时间投资。)

我们使用魔术CTRL + F查找所需的proc。:)(如果SQL Management Studio像VS一样具有代码导航功能,我们将非常喜欢。

对于后续版本,我们通常具有upgradeSchema,upgradeProc和/或updateDate脚本。对于架构更新,我们尽可能地更改表,并根据需要创建新表。对于proc更新,我们拖放并创建。

这种方法确实会产生皱纹。生成数据库很容易,并且很容易在当前数据库版本上获得新的数据库。但是,必须谨慎对待DAL生成(我们目前通常使用SubSonic),以确保DB / schema / proc更改与用于访问它们的代码完全同步。但是,在我们的构建路径中是一个生成SubSonic DAL的批处理文件,因此,检出DAL代码,重新运行该批处理文件,然后在架构和/或proc更改时都将其全部检出,这是我们的SOP。(当然,这会触发源构建,将共享的依赖关系更新为适当的DLL ...)


2

在过去的经验中,我一直以对数据库更改进行源代码控制的方式来控制,对于产品的每个发行版,总是将所有数据库更改写入脚本并存储在我们正在开发的发行版中。适当的构建过程将根据数据库中存储每个“应用程序”当前版本的表,自动将数据库升级到当前版本。然后,我们编写的自定义.net实用程序应用程序将运行并确定数据库的当前版本,并按照脚本前缀编号的顺序针对该数据库运行任何新脚本。然后,我们将运行单元测试以确保一切都很好。

我们将脚本存储在源代码管理中,如下所示(文件夹结构如下):

我对表和存储过程中的当前命名约定有些不满意,因此我的示例几乎没有显示...

[root]
    [应用]
        [版本]
            [脚本]

\ scripts
    MyApplication \
        1.2.1 \
            001.MyTable.Create.sql
            002.MyOtherTable.Create.sql
            100.dbo.usp.MyTable.GetAllNewStuff.sql

使用将考虑应用程序和版本的Versions表,应用程序将还原每周生产备份,并运行自当前版本以来针对数据库所需的所有脚本。通过使用.net,我们可以轻松地将其打包到事务中,如果发生任何失败,我们将回滚并发送电子邮件,因此我们知道该发行版包含错误的脚本。

因此,所有开发人员都将确保在源代码管理中维护此代码,以便协调发布将确保我们计划针对数据库运行的所有脚本都将成功运行。

这些信息可能比您想要的要多,但是它对我们来说非常有效,并且由于结构原因,很容易让所有开发人员参与进来。

当发布日到来时,运营团队将遵循发布说明,并从源代码管理中拾取脚本,并使用我们在夜间构建过程中使用的.net应用程序对数据库运行程序包,该程序会自动将脚本打包到事务中,因此如果如果发生故障,它将自动回滚,并且不会对数据库造成影响。


1

如果在顶部存在drop / create语句,则存储过程每个sp将获得1个文件,其中的标准文件为。视图和函数也获得自己的文件,因此易于版本化和重复使用。

模式是所有1个脚本的开头,然后我们将进行版本更改。

所有这些都存储在一个Visual Studio数据库项目中,该项目通过以下文件夹结构连接到TFS(@work或VisualSVN Server @home以供个人使用):
-项目
-功能
-模式
-存储过程
-视图


1

在我的公司中,我们倾向于将所有数据库项作为单独的脚本存储在源代码管理中,就像对待单个代码文件一样。首先在数据库中进行所有更新,然后将其迁移到源代码存储库中,以便保留更改历史记录。
第二步,将所有数据库更改都迁移到集成数据库。该集成数据库准确地表​​示了生产数据库在部署后的外观。我们还有一个质量检查数据库,代表当前的生产状态(或上一次部署)。在Integration数据库中完成所有更改后,我们将使用架构差异工具(Red Gate的SQL Server SQL Diff)来生成一个脚本,该脚本会将所有更改从一个数据库迁移到另一个数据库。
我们发现这是相当有效的,因为它生成了一个脚本,可以与安装程序轻松集成。我们经常遇到的最大问题是,开发人员忘记将其更改迁移到集成中。



0

编写所有脚本(对象创建等)并将这些脚本存储在源代码管理中。更改如何到达那里?这是如何完成事情的标准实践的一部分。需要添加表格吗?编写一个CREATE TABLE脚本。更新一个程序?编辑存储过程脚本。

我更喜欢每个对象一个脚本。


0

对于proc,请将带有脚本包装的proc写入普通文件,然后应用这些文件中的更改。如果正确应用,则可以检入该文件,也可以从该文件复制该文件。

对于架构更改,您可能需要检入脚本以逐步进行更改。编写脚本,应用它,然后将其检入。然后可以构建一个过程,以自动依次应用每个模式脚本。


0

我们确实将存储过程保留在源代码控制中。我们(或至少是我)这样做的方法是在项目中添加一个文件夹,为每个SP添加一个文件,然后手动复制并将代码粘贴到其中。因此,当我更改SP时,需要手动更改源代码管理文件。

我希望知道人们是否可以自动执行此操作。


0

我强烈建议在源代码管理中维护架构和存储过程。

保留存储过程的版本,以便在确定有问题时可以回滚它们。

根据您的意思,模式是不太明显的答案。维护在源代码管理中定义表的SQL对于复制环境(prod / dev / user等)非常有用。


0

在我当前的项目中,我们一直在使用另一种方法-尚未将数据库置于源代码控制之下,而是在进入每个发行版时一直使用数据库diff工具编写更改脚本。
到目前为止,它一直运行良好。


0

我们将与应用程序相关的所有内容存储在我们的SCM中。DB脚本通常存储在自己的项目中,但是就像其他任何代码一样对待...设计,实现,测试,提交。


0

我运行一项作业以将其脚本化为正式的目录结构。

以下是从批处理文件调用的VS2005代码(命令行项目),可以正常工作。代码末尾的app.config键。

它基于我在网上找到的其他代码。设置起来有点麻烦,但是一旦您开始工作,它就会很好地工作。

Imports Microsoft.VisualStudio.SourceSafe.Interop
Imports System
Imports System.Configuration

Module Module1

    Dim sourcesafeDataBase As String, sourcesafeUserName As String, sourcesafePassword As String, sourcesafeProjectName As String, fileFolderName As String


    Sub Main()
        If My.Application.CommandLineArgs.Count > 0 Then
            GetSetup()
            For Each thisOption As String In My.Application.CommandLineArgs
                Select Case thisOption.ToUpper
                    Case "CHECKIN"
                        DoCheckIn()
                    Case "CHECKOUT"
                        DoCheckOut()
                    Case Else
                        DisplayUsage()
                End Select
            Next
        Else
            DisplayUsage()
        End If
    End Sub

    Sub DisplayUsage()
        Console.Write(System.Environment.NewLine + "Usage: SourceSafeUpdater option" + System.Environment.NewLine + _
            "CheckIn - Check in ( and adds any new ) files in the directory specified in .config" + System.Environment.NewLine + _
            "CheckOut - Check out all files in the directory specified in .config" + System.Environment.NewLine + System.Environment.NewLine)
    End Sub

    Sub AddNewItems()
        Dim db As New VSSDatabase
        db.Open(sourcesafeDataBase, sourcesafeUserName, sourcesafePassword)
        Dim Proj As VSSItem
        Dim Flags As Integer = VSSFlags.VSSFLAG_DELTAYES + VSSFlags.VSSFLAG_RECURSYES + VSSFlags.VSSFLAG_DELNO
        Try
            Proj = db.VSSItem(sourcesafeProjectName, False)
            Proj.Add(fileFolderName, "", Flags)
        Catch ex As Exception
            If Not ex.Message.ToString.ToLower.IndexOf("already exists") > 0 Then
                Console.Write(ex.Message)
            End If
        End Try
        Proj = Nothing
        db = Nothing
    End Sub

    Sub DoCheckIn()
        AddNewItems()
        Dim db As New VSSDatabase
        db.Open(sourcesafeDataBase, sourcesafeUserName, sourcesafePassword)
        Dim Proj As VSSItem
        Dim Flags As Integer = VSSFlags.VSSFLAG_DELTAYES + VSSFlags.VSSFLAG_UPDUPDATE + VSSFlags.VSSFLAG_FORCEDIRYES + VSSFlags.VSSFLAG_RECURSYES
        Proj = db.VSSItem(sourcesafeProjectName, False)
        Proj.Checkin("", fileFolderName, Flags)
        Dim File As String
        For Each File In My.Computer.FileSystem.GetFiles(fileFolderName)
            Try
                Proj.Add(fileFolderName + File)
            Catch ex As Exception
                If Not ex.Message.ToString.ToLower.IndexOf("access code") > 0 Then
                    Console.Write(ex.Message)
                End If
            End Try
        Next
        Proj = Nothing
        db = Nothing
    End Sub

    Sub DoCheckOut()
        Dim db As New VSSDatabase
        db.Open(sourcesafeDataBase, sourcesafeUserName, sourcesafePassword)
        Dim Proj As VSSItem
        Dim Flags As Integer = VSSFlags.VSSFLAG_REPREPLACE + VSSFlags.VSSFLAG_RECURSYES
        Proj = db.VSSItem(sourcesafeProjectName, False)
        Proj.Checkout("", fileFolderName, Flags)
        Proj = Nothing
        db = Nothing
    End Sub

    Sub GetSetup()
        sourcesafeDataBase = ConfigurationManager.AppSettings("sourcesafeDataBase")
        sourcesafeUserName = ConfigurationManager.AppSettings("sourcesafeUserName")
        sourcesafePassword = ConfigurationManager.AppSettings("sourcesafePassword")
        sourcesafeProjectName = ConfigurationManager.AppSettings("sourcesafeProjectName")
        fileFolderName = ConfigurationManager.AppSettings("fileFolderName")

    End Sub

End Module



<add key="sourcesafeDataBase" value="C:\wherever\srcsafe.ini"/>
<add key="sourcesafeUserName" value="vssautomateuserid"/>
<add key="sourcesafePassword" value="pw"/>
<add key="sourcesafeProjectName" value="$/where/you/want/it"/>
<add key="fileFolderName" value="d:\yourdirstructure"/>

-1

如果您正在寻找简单易用的解决方案,则我们的Sql Historian系统将使用后台进程自动将DDL更改同步到TFS或SVN,这对在数据库上进行更改的任何人都是透明的。以我的经验,最大的问题是使用服务器上所做的更改将代码保留在源代码控制中,这是因为通常您必须依靠人员(甚至是开发人员)来更改他们的工作流程,并记得检查他们的更改。他们已经在服务器上完成了。将负担加到机器上,使每个人的生活变得更加轻松。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.