65.9K
CodeProject 正在变化。 阅读更多。
Home

评估 SQL Server 数据工具

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (13投票s)

2012年4月1日

CPOL

15分钟阅读

viewsIcon

84468

使用 Server Data Tools 进行数据库开发。

引言

微软于 3 月 6 日发布了 SQL Server Data Tools,作为 Visual Studio 2010 的免费扩展。如果您想初步了解 SSDT 是什么,我建议您先阅读上面的链接,然后再返回阅读本文。

SSDT 在理论上提供了一些我一直以来都觉得缺失的功能,这些功能给我留下了深刻的印象,以至于我开始质疑目前使用 SQL Server Management Studio 进行数据库开发的习惯,并决定给它一个机会。

本文旨在帮助您决定是否应该采用 SSDT 进行数据库开发。此外,我还将提供一些关于我在测试过程中遇到的问题以及如何解决它们的建议。

SSDT 的主要功能 

最吸引我的功能是这些:
  • 跨所有数据库对象的模式语法检查;例如,在查询中引用不存在的列会在设计时报错。
  • 重构可能性;例如,重命名列时,更改会自动传播到整个数据库模式。
  • 自动生成部署脚本;这意味着我不再需要维护更改脚本列表,也不用担心脚本文件的正确顺序。
  • 集成开发;这意味着数据库项目与 .Net 项目位于同一个 Visual Studio 解决方案中。
  • 数据库源代码控制;这是声明式方法的结果,完整的数据库模式存在于 Visual Studio 解决方案中 

SSDT 必备的基础功能

尽管这些主要功能很吸引人,但放弃 SQL Server Management Studio 这个公认且可靠的数据库开发平台是一个重大的决定。因此,我还定义了一份我日常数据库开发工作中所需的基础功能列表,SSDT 必须提供这些功能。其中大部分功能对我来说至关重要,这意味着如果缺少任何一项关键功能,我可能还是会继续使用 SQL Server Management Studio。

以下是我定义的基础功能列表: 

  1. 解析对其他生产数据库和系统数据库(如 msdb)的引用
  2. 解析对通过链接服务器连接的其他生产数据库的引用
  3. 支持迁移脚本,以实现数据保留和添加静态数据
  4. 快速可靠地生成部署脚本
  5. 执行和部署单个文件的可能性
  6. 检测目标数据库中的孤立更改 
  7. 与 SQL Server Management Studio 相比,SSDT 的 GUI 响应更迅速
  8. 方便的 T-SQL 编写
  9. 代码片段的扩展使用 

SSDT 基础功能的测试 

定义了我看重的东西之后,本文的主要部分将探讨这些功能在 SSDT 中的实现。

1 解析对其他生产数据库和系统数据库(如 msdb)的引用 

数据库可能相互引用,并且部分存在于不同的 SQL Server 实例上。我通过创建一个 Visual Studio 解决方案来模拟这一点,该解决方案不仅包含要测试的数据库,还包含了主测试数据库引用的其他数据库。这是通过创建一个新的 SSDT SQL Server 数据库项目并导入引用的数据库到项目中来实现的。  

您还可以选择导入包含模式的 SSDT dacpac 文件,但当然,一开始您不会有。为了让您更全面地了解导入数据库后 VS 解决方案的样子,请看这个截图: 

导入后,您需要构建项目,以便 VS 创建引用项目所需的 dacpac 文件。您的构建很可能会失败,因为项目中会有很多警告,甚至错误。错误必须解决,警告可以被抑制,因此不会阻止构建(稍后会详细介绍)。

尽管如此,这意味着您也需要负责引用的数据库,这可能导致该数据库的模式发生更改。这使得您在数据库引用另一个生产数据库之初更难准备就绪。另一方面,这也不是坏事,因为错误和警告是有原因的,修复它们可能会改进您的数据库。

另一个内幕消息是,如果您决定使用 SSDT,您应该将其用于所有相互引用的数据库。这样做可以使您的数据库从一开始就受益于必要的错误修复,并与 SSDT 使用的模式保持一致。这一点很重要,因为如果您想部署一个引用了过时数据库的数据库,部署可能会失败。

创建数据库引用本身很简单,只需右键单击引用并选择添加数据库引用即可。

添加数据库引用时,会打开以下对话框。

除了选择要引用的数据库外,您还可以决定如何引用数据库。您是偏爱变量(如上图所示)还是文字(当数据库变量字段为空时选择)。

变量

SELECT * FROM [$(Database2)].[Schema1].[Table1]

字面量

SELECT * FROM [Database2].[Schema1].[Table1]

使用文字的优点是您可以直接运行引用另一个数据库的脚本。使用变量的优点是,在发布时,您不依赖于被引用数据库的固定名称,因为您可以简单地更改变量的值。

除了生产数据库,您还将引用系统数据库。SSDT 为 msdb 和 master 数据库提供了 dacpac,并且可以在上面的对话框中非常简单地引用它们。一个小缺点是,至少 master dacpac 是不完整的,这意味着,例如,缺少未记录的内部视图,这可能导致您的项目中出现您必须抑制的警告。也许微软将来会添加这些。

您将引用的另一个系统数据库是 tempdb。在我的测试中,没有必要添加对它的数据库引用即可使用临时表,如下所示:

IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..##MyTempTable'))
	DROP TABLE ##MyTempTable;

另一方面,在我引用了在另一个存储过程中创建的临时表时,我收到一个警告。对我来说,看起来临时表的创建语句必须包含在使用临时表的脚本中。否则会出现引用警告。

2 解析对通过链接服务器连接的其他生产数据库的引用

添加对不同服务器上数据库的引用很容易,可以在上面的“添加数据库引用”对话框中完成。在“数据库位置”组合框中,选择“不同的数据库/不同的服务器”,然后定义服务器名称和/或变量。之后,您可以像这样使用链接服务器引用(使用了变量): 

SELECT 
		 [Id], [ExtId], [ISIN]
	        FROM
		 [$(OtherServer)].[$(Database3)].dbo.Security

需要注意的一点是,链接服务器是服务器对象,而不是数据库对象。这意味着如果您选中了“仅包含应用程序范围的对象”(我一直这样做),您将错过链接服务器。我通过使用预部署脚本(稍后会详细介绍)创建链接服务器来解决这个问题,如下所示:

IF NOT EXISTS(select * from sys.servers where name = N'MyLinkedServer')
BEGIN
	EXECUTE sp_addlinkedserver @server = N'MyLinkedServer', @srvproduct = N'SQL Server';
END

3 支持迁移脚本,以实现数据保留和添加静态数据

重命名列时,会创建一个 alter table 语句,该语句删除现有列并添加新列,这将导致数据丢失。为避免这种情况,您可以在预部署脚本中将要保留的数据(包括相关键)复制到临时表中,并在稍后的后部署脚本中通过 update 语句将数据插回。

虽然不那么关键但仍然重要的一点是能够将静态数据(也称为域数据)添加到新表中,该新表通常由其他表引用。这可以通过在后部署脚本中创建相应的 insert 脚本来完成。

要告知脚本文件它是预部署/后部署脚本,您可以在脚本文件的属性中将“构建操作”更改为“PreDeploy”或“PostDeploy”。 

SSDT 只支持一个 PreDeploy 和 PostDeploy 脚本,但您不必将所有语句都写在一个脚本文件中,可以使用任意数量的脚本,并通过类似这样的引用指令从 PreDeploy 或 PostDeploy 脚本中引用它们:

:r .\FirstPredeploymentScript.sql
:r .\SecondPredeploymentScript.sql

以此方式引用的脚本文件必须将构建操作设置为“none”。

4 快速可靠地生成和部署

要部署,您需要先构建项目,这需要一些时间,具体取决于数据库模式的大小。为了给您一个想法,在一个拥有 230 个表和 660 个存储过程以及视图、函数等数据库上的第一次完整构建,在我的慢速笔记本上大约需要 2 分钟。第一次构建之后,后续构建会快得多。此外,您不需要在每次添加新的数据库对象时都重新构建,因为您可以直接引用它而无需重新构建。发布过程本身也需要一些时间,因为部署脚本(又名增量脚本)会被生成并执行。如果需要,您还可以选择只生成部署脚本,进行审查,然后稍后部署。

在发布时,您可能需要输入变量的值并配置目标数据库的连接。为避免这些重复的步骤,您可以保存部署配置,将其作为项目的一部分,并在解决方案资源管理器中双击文件来重用它们,如下所示:

一个关键的必备条件是 SSDT 在构建部署脚本时能够确定正确的顺序。到目前为止,我还没有遇到任何问题。我还浏览了与 SSDT 相关的论坛,没有发现任何关于错误构建顺序未得到解决的抱怨。这意味着我现在假设这是可靠工作的。

5 执行和部署单个文件的可能性

在编写复杂的查询时,您可能想一遍又一遍地检查结果,以验证您的操作是否正确。您可以通过在项目选项中定义您的开发数据库来做到这一点。

完成此操作后,您可以打开包含查询的脚本文件,选择要执行的 sql 部分,然后通过右键菜单中的“执行”来操作。 

您可能还想在短时间内多次部署查询,而无需使用正式的部署程序。为此,您可以部署单个数据库对象,类似于执行上面的查询。 

请注意,SSDT 会对 alter 语句发出警告,这是正确的,因为 alter 语句不属于 SSDT 的声明式方法。此外,这确保您会将 alter 语句改回 create,因为否则项目将无法构建。

事实上,编写 alter 语句是 SSDT 所称的在线开发(也称为命令式开发),与离线开发(也称为声明式开发)相对。在进行在线开发时,您还可以利用调试存储过程的可能性,就像您编写 C# 或 VB.net 代码一样,只需在 SQL Server 对象资源管理器中选择要调试的过程即可。

6 检测目标数据库中的孤立更改 

有时,生产数据库可能被管理员直接更改,以进行快速 bug 修复或其他原因。如果这些更改没有反映在 SSDT 项目中,当项目部署到生产系统时,它们就会丢失。这意味着必须有一种方法来检查生产数据库中是否存在缺失的更改。这可以通过使用内置的模式比较来手动完成。 

在截图中,我在进行与 SSDT 项目模式的模式比较之前,对已部署的数据库进行了一些更改。差异如上所示。一个痛点是必须手动进行,当您想部署许多更改时,这可能会变得相当复杂。此外,没有任何东西能阻止您在忘记检查生产数据库的更改时部署这些更改。

我还缺少的是能够生成易于阅读的差异报告的能力,我可以将其发送给其他开发人员来讨论可能的数据库迁移。

7 与 SQL Server Management Studio 相比,SSDT 的 GUI 响应更迅速

显而易见,Visual Studio 是一个比 SQL Server Management Studio 功能更强大的产品,而不幸的是,这也意味着产品加载需要更长时间,可能看起来有些臃肿,有时响应速度比 SQL Server Management Studio 慢。如果您已经熟悉 Visual Studio 2010,您就会知道会发生什么,我认为这取决于个人偏好,您是否觉得与 SQL Server Management Studio 相比使用它不舒服。我自己很喜欢 Visual Studio,可能主要是因为我已经习惯了它,而且我还记得当我们从 SQL Server 2000 Enterprise Manager 切换到 SQL Server Management Studio 时,我一开始多么不喜欢它。今天,我再也不想回去了。

8 方便的 T-SQL 编写 

SSDT 项目提供 intellisense,这本身就很好,但如果您习惯使用 SQL Server Management Studio 中的第三方产品,并且您喜欢它,那么它就不那么好了。就我而言,第三方产品是 devart 的 SQL Complete,它也集成到 Visual Studio 2010 中,但似乎与其当前版本的 SSDT 数据库项目类型 不兼容。事实上,使用 SSDT 的 intellisense,您无法获得对“Select”、“Inner join”等典型 SQL 关键字的支持,但 intellisense 仅限于数据库模式本身(表名、列名、变量等)。它也反应有些迟钝,例如,在连接表时不会提出列连接。这与缺少查询编辑器相结合,使得编写查询不如 SQL Server Management Studio。在一个演示文稿中,我看到查询编辑器是一个新版本 SSDT 中可能引入的功能,我也希望我喜欢的第三方产品在后续版本中也能与 SSDT 兼容。

9 代码片段的扩展使用 

这是另一个生产力功能,就像 intellisense 一样,我不想错过它,并且在 SQL Server Management Studio 中编写查询和在 Visual Studio 中编程时都经常使用它。除了能够使用代码片段,添加自己的代码片段到代码片段集合也很重要。在 Visual Studio 中,您可以使用“代码片段管理器”随时随地完成此操作。不幸的是,编辑一个新代码片段很麻烦,因为我现在看不到任何支持 SSDT 代码片段的编辑器。这意味着您需要手动编写,这很容易做到,但需要一些工作。 

除此之外,在 Visual Studio 中使用代码片段很有趣,而且——就我而言——它的处理方式比 SQL Server Management Studio 更好,因为通过制表符替换变量部分非常用户友好。

我希望将来也能为 SSDT 代码片段提供代码片段编辑器。 

基础必备功能总结

我的列表中没有 SSDT 不支持的功能,但有些功能仍有改进的空间。我希望随着 SSDT 的普及,微软将进一步改进该产品;第三方供应商将确保与 SSDT 的兼容性;开源扩展将提供更多内容。

SSDT 主要功能总结

我还想简要评论一下本文开头提到的主要功能。

模式语法检查 

这真的很棒,帮助我发现了一个生产数据库模式中的一些不一致之处。大多数是关于很久以前根据用户需求构建但今天已不再使用的查询(存储过程和视图)。

如果您的存储过程引用了一个不存在的列,它看起来是这样的:

 

重构可能性

与 .Net 编程中的重构相比,SSDT 的重构感觉有些逊色。您只有四种重构类型,其中“展开通配符”功能在 SQL Server Management Studio 中使用插件 SQL Complete 也可以实现。我最喜欢的是在整个模式中重命名数据库对象(如列)的功能。尽管动态 SQL 没有被考虑在内,但此功能可以节省大量时间。 

重命名列从“Phone”到“PhoneNumber”看起来是这样的:

自动生成部署脚本

我已经在基础功能的第四点中处理了这个问题,只想总结一下,它在测试时运行良好,与手动维护的脚本集合相比,有助于简化部署。

集成开发 

当数据库项目具有 .Net 对等体时,集成开发是一个重要主题,我看到了它在透明度方面的优势,与存在于 Visual Studio 解决方案之外的脚本文件集合相比。 

直接在 SSDT 项目中开发 CLR 数据库对象(如函数等),这也很方便,因为它们自然属于那里。

数据库源代码控制 

这会将集成开发提升到另一个层次。我在测试中没有太多使用源代码控制,但我猜想数据库模式的源代码控制可以顺利地与您现有的源代码控制方式集成。事实上,由于声明式方法,数据库现在只是一堆文件。

结论

在测试过程中,尤其有趣的是看到数据库开发的声明式方法发挥作用,能够进行一些重构,将更改提交到源代码控制,而不必担心脚本必须执行的顺序。

我有点怀念我习惯的扩展智能提示支持,以及那个不存在的查询设计器,它常常是构建任何类型查询的起点。我还怀念我的代码片段集合,并且遇到了一个奇怪的 bug,每次打开 Visual Studio 都会复制所有代码片段。

现在的问题是:我会采用 SSDT 吗?

抱歉,这并非我一个人能决定的,而是我所属团队的决定,尚未做出,所以我无法告知。但我认为,最好的做法是您自己玩玩 SSDT,自己去了解并做出决定。 

另外请记住,根据我的阅读,微软非常重视 SSDT,并且很可能会在其功能方面进行扩展,这意味着即使您现在决定不使用它,当新版本发布时,您也可以考虑改用它。

无论如何,无论是以命令式还是声明式的方式,都祝您好运! 

© . All rights reserved.