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

将 SQL Server 2005 数据库图脚本化到文件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (54投票s)

2006年8月7日

CPOL

5分钟阅读

viewsIcon

346849

downloadIcon

5146

将数据库图表 *保存在数据库外部* 的 Transact-SQL 文本文件中,用于备份和/或源代码管理。

引言

Microsoft SQL Server 2000 具有一项功能,可让您生成架构图。这些图表以自定义二进制格式保存在 Enterprise Manager 的 [dtproperties] 表中——它们会与您的其他数据一起备份,但 *不易* 在数据库之间传输或添加到源代码管理(如 Visual SourceSafe)。

为了将图表移动到另一个数据库(或将其转换为“文本”格式以便进行源代码管理),您需要从 [dtproperties] 中提取二进制数据,并将其转换为更易于使用的格式——Clay Beatty 编写了一个针对 SQL Server 2000 的工具来执行此操作

本文源代码 包含一个类似的工具,已重写为适用于 SQL Server 2005。它由一个存储过程和一个函数组成,它们协同工作以生成一组 INSERT/UPDATE 语句,您将这些语句应用于数据库以恢复源图表。

背景:SQL Server 2000 中的脚本图表

我最初是在 Google Groups 上看到了 Clay Beatty 的 usp_ScriptDatabaseDiagrams 存储过程,用于脚本图表,以及使其正常工作所需的另外两个对象:ufn_VarbinaryToVarcharHexusp_dtpropertiesTextToRowset

在过去的两年里,我一直在使用 usp_ScriptDatabaseDiagrams——因为我们的(“敏捷”)开发方法要求在持续集成过程中从脚本重建数据库,所以如果我们无法以某种方式持久化数据库图表,就会“丢失”它们。

能够脚本化图表意味着也可以在图表工具中直接进行一些“数据库文档记录”。这样完成的文档会方便地与数据库本身一起存储(因此其他开发人员在维护时很容易发现)。

SQL Server 2005

在我们的持续集成过程中,SQL Server 2005 的首批升级问题之一就是图表脚本失败……结果发现 SQL Server 2005 的一些更改破坏了 2000 年的代码。

  • 图表数据现在存储在 [sysdiagrams] 中,而不是 [dtproperties] 中。
  • [sysdiagrams] 每个图表只有一行,而 [dtproperties] 有七行。
  • SQL Server 2005 引入了 VARBINARY(MAX) 数据类型。

SQL Server 2000 脚本中有大量代码用于管理 [dtproperties] 行(DtgSchemaOBJECTDtgSchemaGUIDDtgSchemaNAMEDtgDSRefBYTESDtgDSRefDATADtgSchemaBYTESDtgSchemaDATA),这些行很可能存在 *因为* SQL Server 2000 对二进制数据的支持很笨拙。因此,这几乎是 600 行 Transact-SQL!

新的 [sysdiagrams] 表架构、VARBINARY(max) 的添加和 UPDATE 语句的增强,意味着旧脚本实际上不适用于 SQL 2005,必须从头重写。

关于新的 2005 代码

Tool_VarbinaryToVarcharHex 这个 **用户定义函数** 接收二进制数据作为参数,并输出其十六进制字符串表示。它是图表脚本过程的辅助函数。
Tool_ScriptDiagram2005 这个 **存储过程** 需要一个图表名称,它会从 [sysdiagrams] 中解析该名称。它会生成一组 INSERT 语句,在应用于具有相同架构的数据库时会重新创建图表。

工作原理

SQL Server 2005 的差异如此之大,以至于图表脚本被重写了——大约 120 行(带有很多 PRINT 语句)。远少于 SQL Server 2000 所需的 600 行!它执行三个主要步骤:

1) 获取源图表 ID 和二进制数据的大小

使用新的 SQL Server 2005 DATALENGTH 来确定我们需要处理多少数据(对步骤 #3 很重要)。我们还生成一个变量 @DiagramSuffix,用于确保图表名称唯一(未显示)。

SELECT 
    @diagram_id=diagram_id    
,    @size = DATALENGTH(definition) 
FROM sysdiagrams 
WHERE [name] = @name

2) 生成一个 INSERT 语句,该语句会在 [sysdiagrams] 中创建新行

此脚本基本上是从当前 [sysdiagrams] 行中选择值,并构建一个 INSERT 语句,通过 PRINT 命令输出。请注意,[definition] 列(包含图表的二进制数据)设置为 **Ox**——一个空的十六进制。这在 使用大型值数据类型UPDATE.Write 时*很重要*,因为您*不能*对具有 NULL 值的列进行 .Write 操作。

SELECT @line =  
     'INSERT INTO sysdiagrams ([name], 
     [principal_id], [version], [definition])'
     + ' VALUES (''' + [name] + '''+@DiagramSuffix, '
     + CAST (principal_id AS VARCHAR(100)) + ', '
     + CAST (version AS VARCHAR(100))      + ', 0x)'
FROM sysdiagrams 
WHERE diagram_id = @diagram_id
PRINT @line

3) 创建 UPDATE 语句,抓取 [definition] 的块

在从 1 到 DATALENGTH([definition]) 的 WHILE 循环中,使用辅助函数 Tool_VarbinaryToVarcharHex 将二进制数据的块转换为可以 PRINT 输出并保存为文本的十六进制字符串。

WHILE @index < @size
BEGIN
    SELECT @line =  
     'UPDATE sysdiagrams SET [definition] .Write ('
    + ' 0x' + UPPER(dbo.Tool_VarbinaryToVarcharHex (
                    SUBSTRING (definition, @index, @chunk)))
    + ', null, 0) WHERE diagram_id = @newid '
    FROM    sysdiagrams 
    WHERE    diagram_id = @diagram_id

    PRINT @line
    SET @index = @index + @chunk
END

TRY/CATCH 错误处理

原始脚本中有大量的 IF @@ERROR <> 0 错误处理。相比之下,新的 2005 错误处理 要简单得多——语法对于 .NET 语言开发者来说很熟悉。

BEGIN TRY
    INSERT INTO sysdiagrams ([name], [principal_id], 
                             [version], [definition]) 
    VALUES ('All'+@DiagramSuffix, 1, 0, 0x)
    SET @newid = SCOPE_IDENTITY()
END TRY
BEGIN CATCH
    RETURN
END CATCH

这并不是 SQL 中 TRY/CATCH 用法的完美示例——没有 TRANSACTION 用法(所以没有显示 COMMIT/ROLLBACK),但您能理解意思。

要了解 Tool_VarbinaryToVarcharHex 的工作原理,请阅读 代码 中的注释——这在很大程度上(除添加了代码注释外)与 Clay 免费发布的 SQL Server 2000 版本相同。

运行“代码”

在数据库中执行这两个脚本后,使用它们生成图表的 INSERT/UPDATE 语句,如下所示:

exec Tool_ScriptDiagram2005 'All Tables'

这将创建一个看起来像这样的脚本(注意新的 SQL Server 2005 UPDATE.Write 命令)。

PRINT 'Create row for new diagram'
INSERT INTO sysdiagrams ([name], [principal_id], [version], [definition]) 
VALUES ('All'+@DiagramSuffix, 1, 0, 0x)
 
SET @newid = SCOPE_IDENTITY()
 
PRINT 'Write diagram id ' + CAST(@newid AS VARCHAR(100)) + ' into new row '
 
PRINT 'Now add all the binary data...'
UPDATE sysdiagrams 
    SET [definition] .Write ( 0xD0CF11E0A1B11AE1, null, 0) 
    WHERE diagram_id 
UPDATE sysdiagrams 
    SET [definition] .Write ( 0x0600000000000000, null, 0) 
    WHERE diagram_id 
-- ... Many more UPDATE rows

每个 UPDATE 会向 [sysdiagram] 行添加更多二进制数据,直到您可以将 UPDATE 保存到磁盘,将其添加到源代码管理,等等……当您想检索图表(到数据库的另一个副本/版本/备份)时,只需运行 UPDATE 脚本。输出将如下所示:

=== Tool_ScriptDiagram2005 restore diagram [all] ===
Suffix diagram name with date, to ensure uniqueness
Create row for new diagram
Write diagram all into new row (and get [diagram_id])
Now add all the binary data...
=== Finished writing diagram id 75  ===
=== Refresh your Databases-[DbName]-Database Diagrams 
    to see the new diagram ===</CODE>

在 SQL Server Management Studio 中右键单击 **数据库关系图** 文件夹,然后选择“刷新”。您的已恢复图表应已准备好查看!

结论

希望人们发现这个脚本与我发现 Clay Beatty 的 SQL Server 2000 原始脚本一样有用。

历史

  • 2006-08-07:发布于 CodeProject。
© . All rights reserved.