数据库对象脚本编程基础知识

日期: 2010-08-15 作者:Roman Rehak翻译:孙瑞 来源:TechTarget中国 英文

尽管SQL Server客户端工具在创建数据库对象脚本方面有着不错的功能表现,但它们的灵活性也许并没有达到人们所期望的程度。为了这一点,数据库开发者和DBA开始自己编写脚本生成工具,来实现自动生成脚本的功能。   举个例子,许多公司都有自动生成数据库对象脚本的方式,比如在文本文件中使用存储过程和视图,然后放到源码控制系统进行检测,比如Microsoft Visual SourceSafe。先从SQL Server 2005说起,SQL Server Management Objects为DBA提供了必要的API,来生成数据库对象脚本。

因此,在本文中就让我们来介绍一下SMO脚本的基础知识和一些使……

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

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代码了。

翻译

孙瑞
孙瑞

相关推荐