尽管SQL Server客户端工具在创建数据库对象脚本方面有着不错的功能表现,但它们的灵活性也许并没有达到人们所期望的程度。为了这一点,数据库开发者和DBA开始自己编写脚本生成工具,来实现自动生成脚本的功能。 举个例子,许多公司都有自动生成数据库对象脚本的方式,比如在文本文件中使用存储过程和视图,然后放到源码控制系统进行检测,比如Microsoft Visual SourceSafe。先从SQL Server 2005说起,SQL Server Management Objects为DBA提供了必要的API,来生成数据库对象脚本。
因此,在本文中就让我们来介绍一下SMO脚本的基础知识和一些使……
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
![TechTarget微信公众号二维码](/wp-content/uploads/res/images/spriteimg/ttweixin.jpg)
TechTarget
官方微博
![TechTarget中国官方微博二维码](/wp-content/uploads/res/images/spriteimg/ttweibo.jpg)
TechTarget中国
尽管SQL Server客户端工具在创建数据库对象脚本方面有着不错的功能表现,但它们的灵活性也许并没有达到人们所期望的程度。为了这一点,数据库开发者和DBA开始自己编写脚本生成工具,来实现自动生成脚本的功能。
举个例子,许多公司都有自动生成数据库对象脚本的方式,比如在文本文件中使用存储过程和视图,然后放到源码控制系统进行检测,比如Microsoft Visual SourceSafe。先从SQL Server 2005说起,SQL Server Management Objects为DBA提供了必要的API,来生成数据库对象脚本。因此,在本文中就让我们来介绍一下SMO脚本的基础知识和一些使用技巧,通过本文希望读者可以更好地掌握SMO编程。
如果你还不太熟悉SMO编程的话,那么第一步我们就需要了解一下如何在Visual Studio中添加SMO库,因为在本文中的许多代码都是由作者自己创建的示例程序。
SMO脚本的基本原理是非常简单的,当你连接好服务器,然后选择你想要使用的对象并使用Script() method。任何能够使用SQL脚本创建的数据库对象,都需要在SMO中部署一个Script()method。这个method还接受一个可选的参数,叫做ScriptingOptions,它是一系列可用脚本选项的集合,使用true/false值来定义输出中包含哪些脚本。而学习这些脚本以及如何使用它们在SMO脚本编程方面是特别重要的。
以下的代码显示了包含进来的脚本选项:
ScriptingOptions scriptingOptions = new ScriptingOptions(); scriptingOptions.ExtendedProperties = chkScriptExtendedProperties. Checked; scriptingOptions.IncludeHeaders = chkScriptHeaders.Checked; scriptingOptions.IncludeIfNotExists = chkScriptNotExists.Checked; scriptingOptions.Permissions = chkScriptPermissions.Checked; scriptingOptions.ScriptDrops = chkScriptDrop.Checked; scriptingOptions.IncludeDatabaseContext = chkScriptDBContext. Checked; if(cmbVersion.SelectedItem.ToString() == "SQL Server 2000") scriptingOptions.TargetServerVersion = SqlServerVersion.Version80; if (cmbVersion.SelectedItem.ToString() == "SQL Server 2005") scriptingOptions.TargetServerVersion = SqlServerVersion.Version90; if (cmbVersion.SelectedItem.ToString() == "SQL Server 2008") scriptingOptions.TargetServerVersion = SqlServerVersion.Version100; |
前六个选项接受true或false布尔值,TargetServerVersion属性决定了目标SQL Server的版本。该属性类型是SqlServerVersion对象,它支持三个版本的SQL Server:2000、2005和2008。
在你的代码中,你可以对独立的对象进行脚本编写,或者对同一类型的对象进行脚本编写。下面的代码显示了如何对所有的数据库存储过程进行遍历,并把它们编写到单一的文件中:
foreach (StoredProcedure sp in db.StoredProcedures) { if (sp.IsSystemObject) continue; script = ScriptObject(sp as IScriptable, scriptingOptions, chkScriptDrop.Checked); … } |
类似地,你还可以遍历其它类型的对象,比如视图或者用户定义函数等。注意,该代码将跳过系统对象,因为你不大可能去对一个系统存储过程进行脚本编写。事实上,当你对系统对象进行脚本编写的时候,SQL Server肯定会报错,因为那部分代码是无法进行脚本编写的。
该代码调用了我自的一个类函数ScriptObject(),而第一个参数是一个SMO接口,叫做IScriptable。这个接口允许你将任何可以编写脚本的对象施放到IScriptable之中。举个例子,我要为一个视图编写脚本,使用的是相同的函数,我可以使用同存储过程一样的方式来实现,代码如下:
script = ScriptObject(view as IScriptable, scriptingOptions, chkScriptDrop.Checked); The code in the ScriptObject() method looks like this: private stringScriptObject(IScriptable so, ScriptingOptions options, bool includeDrop) { StringCollection strings; StringBuilder sb = new StringBuilder(); // save these values to preserve them bool scriptDrops = options.ScriptDrops; bool includeIfNotExists = options.IncludeIfNotExists; if(includeDrop) { // script DROP separately strings = so.Script(options); foreach (string str in strings) { sb.Append(str + Environment.NewLine + "GO" + Environment.NewLine + Environment.NewLine); } // reset DROP back to false options.ScriptDrops = false; options.IncludeIfNotExists = false; } // now script CREATE strings = so.Script(options); foreach (string str in strings) { sb.Append(str + Environment.NewLine + "GO" + Environment.NewLine + Environment.NewLine); } // restore the original values options.ScriptDrops = scriptDrops; options.IncludeIfNotExists = includeIfNotExists; return sb.ToString(); } |
该代码为一些脚本选项做了特殊的操作,比如如果你将选项设置为生成一个DROP声明,它就不会生成CREATE声明。然而,我的代码调用了两次脚本method,一次是生成DROP声明,一次是生成CREATE声明。在DROP生成之后,我可以将ScriptDrops选项设置为false,然后再允许生成CREATE。
而IncludeIfNotExists选项则更加诡异一些。如果它是true的,那么同ScriptDrops一起将生成一个有条件的DROP,看上去就如下所示:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ufnGetAccountingEndDate]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) DROP FUNCTION [dbo].[ufnGetAccountingEndDate] But if the IncludeIfNotExists option is true when generating CREATE it will script the CREATE code as dynamic SQL, like this: IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ufnGetAccountingEndDate]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) execute dbo.sp_executesql @statement = N' CREATE FUNCTION [dbo].[ufnGetAccountingEndDate]() RETURNS [datetime] AS BEGIN RETURN DATEADD(millisecond, -2, CONVERT(datetime, ''2004-07-01'', 101)); END; ' |
这样生成代码因为CREATE对于许多对象来说,是第一个命令,所以你不能在它前面使用IF EXISTS。由于我不太喜欢这样的形式,而且我认为许多DBA都应该不喜欢,所以我就在DROP声明被编写脚本之后,将这一个选项设置为false了。这样的话,结果就是如果对象存在,我就会drop掉,然后再创建它。相反地,如果对象不存在,我就create它。
你可能注意到了,我在代码中保留了两个设置(ScriptDrops 和IncludeIfNotExists),在函数的结尾我还原了原始的Value。这样做的原因,是函数经过重复的调用,而调用函数的对象是不同的。我们需要区分函数内的不同设置才能生成CREATE脚本,而且还需要还要设置回来,这样下一个对象就可以以同样的方式进行脚本编写了。
下面是一个由我的程序生成的脚本:
因此,这些就是SMO脚本编程的基础知识,但是同以往一样,这些代码都是可以通过修改来为你服务的,设置不同的脚本选项就可以帮助你生成你所需要的SQL代码了。
作者
翻译
相关推荐
-
最新SQL Server工具解决数据库文档难题
数据库开发者总是避免以文档形式记录自己的代码和结构,而当有其他人要接手他们的项目时,才会感到问题的严重性。
-
Oracle数据库中四大应用服务之间的密切关系
本文主要是对Oracle数据库中service_name、tablespace、schema、user四者之间的关系一些分析与实际应用中的举例。
-
在SQL Server中实现Oracle的Sequence
如果大家在Oracle里面用惯了Sequence,要在SQL Server里实现Sequence,就会发现没有现成的Sequence对象可以Create了,本文将对这一问题进行深入探讨。
-
SQL Server数据导入导出的几种方法
在涉及到SQL Server编程或是管理时一定会用到数据的导入与导出,导入导出的方法有多种,在这里我们介绍几种比较方便的操作方法。