SQL SERVER

SQL Server数据库文件恢复技术

SQL Server数据库备份有两种方式,一种是使用BACKUP DATABASE将数据库文件备份出去,另外一种就是直接拷贝数据库文件mdf和日志文件ldf的方式。下面将主要讨论一下后者的备份与恢复。本文假定您能熟练使用SQL Server Enterprise Manager(SQL Server企业管理器)和SQL Server Quwey Analyser(SQL Server查询分析器)
1、正常的备份、恢复方式
正常方式下,我们要备份一个数据库,首先要先将该数据库从运行的数据服务器中断开,或者停掉整个数据库服务器,然后复制文件。
卸下数据库的命令:Sp_detach_db 数据库名
连接数据库的命令:Sp_attach_db或者sp_attach_single_file_db
s_attach_db [@dbname =] ′dbname′, [@filename1 =] ′filename_n′ [,...16]
sp_attach_single_file_db [@dbname =] ′dbname′, [@physname =] ′physical_name′
使用此方法可以正确恢复SQL Sever7.0和SQL Server 2000的数据库文件,要点是备份的时候一定要将mdf和ldf两个文件都备份下来,mdf文件是数据库数据文件,ldf是数据库日志文件。
例子:
假设数据库为test,其数据文件为test_data.mdf,日志文件为test_log.ldf。下面我们讨论一下如何备份、恢复该数据库。
卸下数据库:sp_detach_db 'test'
连接数据库:sp_attach_db 'test','C:/Program Files/Microsoft SQL Server/MSSQL/Data/test_data.mdf','C:/Program Files/Microsoft SQL Server/MSSQL/Data/test_log.ldf'
sp_attach_single_file_db 'test','C:/Program Files/Microsoft SQL Server/MSSQL/Data/test_data.mdf'
2、只有mdf文件的恢复技术
由于种种原因,我们如果当时仅仅备份了mdf文件,那么恢复起来就是一件很麻烦的事情了。
如果您的mdf文件是当前数据库产生的,那么很侥幸,也许你使用sp_attach_db或者sp_attach_single_file_db可以恢复数据库,但是会出现类似下面的提示信息
设备激活错误。物理文件名 'C:/Program Files/Microsoft SQL Server/MSSQL/data/test_Log.LDF' 可能有误。
已创建名为 'C:/Program Files/Microsoft SQL Server/MSSQL/Data/test_log.LDF' 的新日志文件。
但是,如果您的数据库文件是从其他计算机上复制过来的,那么很不幸,也许上述办法就行不通了。你也许会得到类似下面的错误信息
服务器: 消息 1813,级别 16,状态 2,行 1
未能打开新数据库 'test'。CREATE DATABASE 将终止。
设备激活错误。物理文件名 'd:/test_log.LDF' 可能有误。
怎么办呢?别着急,下面我们举例说明恢复办法。
A.我们使用默认方式建立一个供恢复使用的数据库(如test)。可以在SQL Server Enterprise Manager里面建立。
B.停掉数据库服务器。
C.将刚才生成的数据库的日志文件test_log.ldf删除,用要恢复的数据库mdf文件覆盖刚才生成的数据库数据文件test_data.mdf。
D.启动数据库服务器。此时会看到数据库test的状态为“置疑”。这时候不能对此数据库进行任何操作。
E.设置数据库允许直接操作系统表。此操作可以在SQL Server Enterprise Manager里面选择数据库服务器,按右键,选择“属性”,在“服务器设置”页面中将“允许对系统目录直接修改”一项选中。也可以使用如下语句来实现。
use master
go
sp_configure 'allow updates',1
go
reconfigure with override
go
F.设置test为紧急修复模式
update sysdatabases set status=-32768 where dbid=DB_ID('test')
此时可以在SQL Server Enterprise Manager里面看到该数据库处于“只读/置疑/脱机/紧急模式”可以看到数据库里面的表,但是仅仅有系统表
G.下面执行真正的恢复操作,重建数据库日志文件
dbcc rebuild_log('test','C:/Program Files/Microsoft SQL Server/MSSQL/Data/test_log.ldf')
执行过程中,如果遇到下列提示信息:
服务器: 消息 5030,级别 16,状态 1,行 1
未能排它地锁定数据库以执行该操作。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。[brown][/i]
说明您的其他程序正在使用该数据库,如果刚才您在F步骤中使用SQL Server Enterprise Manager打开了test库的系统表,那么退出SQL Server Enterprise Manager就可以了。
正确执行完成的提示应该类似于:
警告: 数据库 'test' 的日志已重建。已失去事务的一致性。应运行 DBCC CHECKDB 以验证物理一致性。将必须重置数据库选项,并且可能需要删除多余的日志文件。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
此时打开在SQL Server Enterprise Manager里面会看到数据库的状态为“只供DBO使用”。此时可以访问数据库里面的用户表了。
H.验证数据库一致性(可省略)
dbcc checkdb('test')
一般执行结果如下:
CHECKDB 发现了 0 个分配错误和 0 个一致性错误(在数据库 'test' 中)。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
I.设置数据库为正常状态
sp_dboption 'test','dbo use only','false'
如果没有出错,那么恭喜,现在就可以正常的使用恢复后的数据库啦。
J.最后一步,我们要将步骤E中设置的“允许对系统目录直接修改”一项恢复。因为平时直接操作系统表是一件比较危险的事情。当然,我们可以在SQL Server Enterprise Manager里面恢复,也可以使用如下语句完成
sp_configure 'allow updates',0
go
reconfigure with override
go





    摘要:日志文件缩小全接触    (全文共4413字)——点击 此处阅读全文


2006年01月10日


    摘要:事务具有ACID属性 即 Atomic原子性, Consistent一致性, Isolated隔离性, Durable永久性    (全文共10579字)——点击 此处阅读全文


2005年12月31日

36. 解决常见的效能问题
什么是瓶颈
发现问题
一般效能瓶颈
SQL Server组态设定
本章总结
在整本书中,您看到了可以使用的工具和可以修改的参数,来帮助您发现与解决效能问题。例如,前一章学到如何利用 SQL 陈述式和预存程序来辨识问题,以及如何调整那些陈述式和程序达成最佳化效能。本章则帮助您简单地找到需要的信息,以便解决各种效能问题,并检视一些其它章节讨论过跟效能有关的主题,提供检验效能问题的参考方案,与说明一些与效能监视和系统调整有关的附加信息。
我们将从复习 瓶颈 (bottleneck)的定义开始。然后看看如何使用 Windows 2000 系统监视器(在 Windows NT 中称为效能监视器),以及如何使用 Microsoft SQL Server Enterprise Manager 来确定效能问题是否存在。接着是如何解决一般效能问题,该问题发生在好几种层级中,包括应用程序、SQL Server、操作系统和硬件等层级。用在系统容量计划的主要规则已经在 第 6 章 说明过,但本章还会再复习一次,因为它们可以用来分析现有的系统,以确定是否需要附加硬件来改善效能。最后将复习前几章提过的好几种 SQL Server 设定参数,用来调整系统效能的改变方式。
在本章的结尾,您将可以识别效能瓶颈,并确定导致瓶颈的原因。虽然不是每次都能解决问题,但是只要肯花时间以及资源来处理这些问题,大部分问题是可以解决的。
什么是瓶颈
 
 瓶颈 一词通常用来讨论软件和硬件效能问题,也就是系统中一个组件或一组组件可能限制系统效能的状况。例如,缺少足够容量的 I/O 子系统会导致一个严重的瓶颈-它会使整个系统变慢。(在本章的 <I/O子系统> 一节中会详细的讨论这种情况。)
几乎所有系统中活动的组件都可能导致瓶颈。瓶颈可以由一个组件所引起,例如一个磁盘,或由一组组件所引起,例如I/O子系统,或由不同组件的组合所引起。例如,您可能首先检测到一个 I/O 子系统瓶颈。解决这个问题的方法是透过增加更多的磁盘来支持发生问题系统中的 I/O 数量(硬件解决方案),或透过最佳化低效率查询来减少 I/O 的发生(软件解决方案),或两者都使用。当 I/O 问题被解决时,可能会发现现在产生 CPU 瓶颈,并需要增加 CPU 的速度或 CPU 的数量。
发现问题
 
要确定系统是否有问题存在,首先要观察系统效能。例如,使用者是否在执行数据库查询或修改时,受到比预期更慢的反应时间。这是效能问题或瓶颈的一般状况。也许您会注意到,当执行某种查询时,系统上所有其它的操作会执行得比平常慢。因此将着重于造成问题的最佳化查询,或者在较少使用者存取系统时,试着同时执行查询来找出原因。
另一个确定是否有问题存在的途径是定期的测试和监控系统。可以使用的工具包括 Windows 2000 系统监视器和 SQL Server Enterprise Manager。本节会学习如何使用这两种工具检查系统的状况,也将学习用在监视 SQL Server 过程的 sp_wh 0-7356-1266-8预存程序。
________________________________________
说明
如果需要使用 SQL Profiler和SQL Query Analyzer 来侦测和 SQL 陈述式有关的效能问题,请参阅 第 35 章 。
________________________________________
系统监视器
 
Windows2000 系统监视器不仅支持 Windows2000 计数器,也支持 SQL Server计数器。这些计数器监控系统功能随时间的变化以确定系统中的状态,例如 CPU 利用的百分率或 SQL Server 快取命中比率。(本章也提供关于特定效能计数器的信息。)您可以随时观察监视器,或将数据记录到档案中,以后再检视。
要使用系统监视器监视系统,请依下列步骤进行:
1. 按 开始 / 程序集 / 系统管理工具 / 效能 ,进入系统监视器窗口。
2. 指定您是否以图表格式、报表格式或记录数据格式来检视计数器数据,或是在工具列上点选合适的按钮,检视之前存在数据记录文件的数据。图36-1显示在 系统监视器 中的图表检视。如果选择检视记录文件,对话框会显示在您开启的档案上。
 
 
图36-1 Windows 2000 效能监视器
3. 要在 效能 窗口中加入一个检视的计数器,请在工具列中按一下加号按钮,会出现 新增计数器 对话框,如图36-2所示。点选 本机计算机计数器 ,检视本机系统的计数器,或者点选 从下列计算机选择计数器 ,并从下拉式清单上选择一个远程计算机名称,检视该计算机的计数器。
 
 
图36-2 「新增计数器」对话框
4. 从 效能对象 下拉式清单上选择 System 对象。这些对象代表系统组件。您选择的对象计数器将显示在对话框左边角落的清单上。要观察所有对象的计数器,按一下 所有计数器 。如果想要监视某些特定的计数器,点选 从清单选取计数器 ,然后选择清单上的计数器。有些计数器不只一种,这些例子都将显示在对话框右边角落的清单上。要选择一个或多个特定例子来检视的话,就点选 从清单选取例项 ,或者点选 所有例项 来检视全部的例子。
5. 按一下 新增 ,所选择的计数器就会新增到 效能 窗口。(如果选择一个计数器的多种例项,它们会全部新增进去。)您可以继续新增计数器。准备要回到 效能 窗口时按一下 关闭 ,您就能看到计数器提供的效能数据。图36-3显示三种计数器回传的结果:Context Switches/Sec、Total Server Memory (KB)和% Processor Time。
 
 
图36-3 实时系统监视器
要将效能数据存入记录文件中,请跟着下面程序:
1. 在 效能 窗口左边窗格中展开 效能记录文件及警示 。在 计数器记录文件 上按一下右键,并从快捷菜单中选择 新增记录文件设定 。出现 新记录文件设定 对话框后,在这里输入您的记录文件设定名称,如图36-4所示,最后按一下 确定 。
 
 
图36-4 「新记录文件设定」对话框
2. 出现新的记录档案后窗口就被命名了。在 一般 签页中,按一下 新增 。 新增计数器 对话框出现,选择您要记录的计数器,就像之前步骤3~5所描述的一样。 一般 签页也让您可以变更记录文件名称,并且指定效能数据多久检查一次。
3. 按一下 记录文件 页签,设定记录档案的附加属性。图36-5显示这些设定,该档案将在它的名称之后加入日期,并且设定成二位档案型态。
 
 
图36-5 新的记录档案窗口中的「记录文件」签页
4. 按一下 排程 页签。这个签页中,您为记录文件指定一个开始和结束时间。您也可以选择开启一个新的记录文件,或者当目前记录文件关闭时执行指令。
5. 按一下 确定 关闭窗口,并将记录档案信息存盘。如果您选择立即开启记录,当您点选 确定 时,记录就会开始启动。这个记录档案的项目将显示在 效能 窗口,如图36-6所示。
您可以在有规律的基础上使用效能监视器来检查系统的状态。每日或每星期的监控是个好主意,这样您可以了解您的系统,以便于当异常的现象发生时,您能够识别这个现象的原因。将效能数据保存到记录档案以备稍后的检查,这也是建议的方法-记录档案中的数据总会派上用场,您可以比较系统更改前后的效能数据,确定这个更改是否是好的。您也可以使用这些记录文件来比较使用者和系统活动是如何从一种状态变更到另一种状态的。例如,您可能注意到,在本月的最近几天,使用者活动比其它时间要多。这样您将确保您的系统能够处理在这些尖峰值时的负载。

 
 
图36-6 效能 窗口,显示一个新计数器记录的项目
Enterprise Manager
 
除了自动的日常管理功能以外,Enterprise Manager 可以用来协助监控 SQL Server 过程与锁定。(请参阅 第 19 章 关于锁定的信息。)例如,您可以收集关于程序锁定和对象锁定的数据-在这些情况下,一个对象可以是数据表、数据库或暂存数据表。要检视这些信息,请按照下列步骤操作。
1. 在 Enterprise Manager 窗口展开 SQL Server/SQL Server群组/管理资料夹/目前活动 ,如图36-7所示。 目前活动 数据夹包含三个数据夹: 处理器信息 、 锁定/处理序识别码 和 锁定/对象 。
 
 
图36-7 展开 Enterprise Manager 中的「目前活动」资料夹
2. 按一下 处理器信息 来检视当前连接到 SQL Server 的使用者名称和他们的程序 ID;这些使用者程序状态(执行、睡眠、或是背景);他们连接了哪些数据库;他们执行了哪些指令和应用程序;等待时间(使用者花在等待可用资源的时间);CPU、实体 I/O、和每个程序的内存使用量;以及每个程序的封锁状态(程序封锁他人或是被他人封锁)。要看这些信息,必须将窗口滚动条往右移。图36-8显示了这些信息。
3. 按一下 锁定/处理序识别码 ,在右侧窗格中检视系统程序识别码(SPID)的清单,如图36-9所示。在右侧窗格的一个 SPID 上按二下,以显示 处理序详细信息 对话框,如图36-10所示。这个对话框显示了程序执行的最后一个 T-SQL 指令。
 
 
图36-8 Enterprise Manager 中的「处理器信息」

 
 
图36-9 显示在「锁定/处理序识别码」窗格的 SPID

 
 
图36-10 「处理序详细信息」对话框
4. 展开 锁定/处理序识别码 数据夹,以检视当前锁定的 SPID,如图36-11所示。
 
 
图36-11 展开的「锁定/处理序识别码」数据夹
5. 按一下左侧窗格中的一个 SPID 以检视该程序特定的锁定信息,如图36-11所示。这些信息包括锁定的类型、锁定的模式、锁定的状态和锁定的拥有者。锁定的类型包括下列之一:
o  RID 数据列锁定
 
o  KEY 索引中的数据列锁定
 
o  PAG 数据或索引页锁定
 
o  EXT Extent锁定
 
o  TAB 数据表锁定,包含该数据表的所有数据和索引页
 
o  DB 数据库锁定
 
锁定模式可以是下列之一:
o  S 共享锁定
 
o  X 独占锁定
 
o  U 更新锁定
 
o  BU 大量更新锁定
 
o  IS 意图(intent)共享
 
o  IX 意图独占
 
o  SIX 具有意图独占的共享
 
o  Sch-S 编译查询的结构描述(schema)锁定
 
o  Sch-M DDL 操作的结构描述锁定
 
锁定的状态可以是下列之一:
o  GRANT 指锁定将被授予该程序
 
o  WAIT 表示该程序由其它程序封锁,并等待一个锁定
 
o  CNVT 表示锁定被转换成另一种锁定类型
 
6. 展开 锁定/对象 数据夹,检视具有锁定的对象的清单,如图36-12所示。可以被锁定的对象有数据表、暂存数据表、数据库等等。
 
 
图36-12 展开的「锁定/对象」数据夹
7. 按一下被锁定的数据库或数据表名称,在右侧窗格中检视它的锁定信息,如图36-13所示。这些信息和在 锁定/处理序识别码 数据夹中点选 SPID 后出现的内容相同,只是观看的角度不一样而已。
 
 
图36-13 检视对象的锁定信息
sp_who 预存程序
 
您也可以在 Query Analyzer 或 OSQL 提示中执行下面指令,来检视程序的信息:
sp_who active
GO
在 Query Analyzer 中执行这个指令的结果如图36-14。如果一个程序被锁定了,blk字段将显示正在锁定程序的SPID。
当使用者抱怨交易太慢时,您可以执行这个指令来找出问题。很多时候您会发现大部份被封锁的程序是被另一个程序封锁的,一旦找出产生问题的程序所在,就能确定封锁这么久的原因。

 
 
图36-14 执行 sp_who 的结果
您应该经常监控锁定,以确定是否有些程序占有一个锁定的时间太长,以及是否程序经常被其它程序封锁(它们有 WAIT 状态)。但是通常使用者的抱怨多半由于封锁问题引起的响应时间太慢。如果封锁发生得太频繁或太长时间,您可能要确定哪个程序占有独占锁定或数据表锁定。这些锁定可能是导致封锁的原因,并监控程序执行的 SQL 陈述式。然后如果可能试着最佳化这些陈述式,使它们更快的释放锁定或避免占有数据表锁定。一般而言,一个程序用很多时间等待获得一个锁定时,该程序会使用更多的时间来完成。因此,减少锁定竞争可以提高交易响应时间。
________________________________________
相关信息
关于锁定的更多信息,请参阅< 在线丛书 >并索引 显示锁定 ,并选择在 找到的主题 对话框中的 显示锁定信息 。
________________________________________
一般效能瓶颈
 
您已经了解如何使用效能监视工具,如系统监视器、Enterprise Manager、Query Analyzer 和 Profiler,而您也准备要对付效能瓶颈了。在本节中,我们将看到一些很普通的效能瓶颈和不同的解决方案。这些瓶颈大部分是相互关联的,且一个瓶颈可能伪装成另一种瓶颈的形式。您必须寻找硬件和软件导致的瓶颈-很多效能问题发生于瓶颈的组合。可能导致瓶颈的硬件包括 CPU、内存和 I/O 子系统;可以导致瓶颈的软件包括 SQL Server 应用程序和 SQL 陈述式。下面章节我们将更详细地检验每种问题。
CPU
 
一个普通的效能问题就是缺少马力。系统的处理能力取决于系统中 CPU 的数量、类型和速度。如果您没有足够的 CPU 能力,您可能无法快速的处理交易以令使用者满意。要使用系统监视器来确定 CPU 利用的百分率,请检查 Processor 对象中的 %Processor Time 计数器(选择多处理器系统中的所有 CPU)。如果您的 CPU 长时间执行在 75% 或更高的情况下(75% 是根据 第 6 章 设定的规则所要求的最大值),您更可能遇到 CPU 瓶颈。如果您看到了低于 60% 的稳定 CPU 使用率,您仍然可以透过在系统中增加更快的 CPU 或更多的 CPU 中获益。
在决定升级您的 CPU 之前,确定监控了系统的其它特性。例如,如果您的 SQL陈述式效率很低,您可能执行了很多非必要的程序,而最佳化这些陈述式就可以帮助您降低 CPU 利用。或者假设 SQL Server 数据快取的快取命中比率低于 90%。您可能需要增加内存到数据快取中(也就是增加 max server memory 参数或增加系统的物理内存),这允许更多的数据存入快取和更少的实体磁盘 I/O 操作,导致了较低的 CPU 使用率。有时只增加处理器,您就可以获得更好的系统效能,特别是您从单处理器系统开始。然而,并不是所有应用程序都能适应多处理器系统的规模。SQL Server 本身的延展性很好,但并不是所有执行的 SQL 陈述式都需要延展性。一个程序一次只能在一个 CPU 上执行,而且对于单个 SQL 陈述式单个 CPU 已经足够了。为了效能的延展,您的 SQL Server 必须同时执行很多 SQL 陈述式-多个陈述式可以同时在不同 CPU 上执行,因此多个 CPU 能同时处理这些陈述式。
一般而言,您可以透过使用更多和更快的 CPU 来提高效能。然而,在某些情况下,在增加更快的 CPU 之同时,您必须扩大内存和 I/O 容量,否则您可能只将这个瓶颈转移到另一个位置,甚至可能是新的 CPU。例如,如果您原来有一个 CPU 瓶颈,而您透过增加一个 CPU 解决了这个问题,但您可能会发现您的系统执行了更多的工作,因此导致了更多的磁盘 I/O,然后您会发现一个 I/O 瓶颈的发生。另外,确保检查您决定增加的 CPU 的快取大小。CPU 的快取越大,效能将越好,特别是在多处理器系统中。
简单地说,如果您决定您需要更多的处理能力,您可以增加 CPU 或用更快的代替现有 CPU。例如,如果您的系统有两个 CPU,但是可以扩展为四个,那么可以增加两个同类型的 CPU,或替换四个全新更快的 CPU。如果您的系统已经具有了最大数量的 CPU,而您又需要更多的处理能力,那么就用更快的 CPU 来替换它们。例如,让我们假设您有四个 200 MHz 的 CPU。您可以用更快的 CPU 来替换它们,例如 500 MHz。更快的 CPU 将执行更快的完成程序。
内存
 
内存是 SQL Server 效能最关键性的组件之一。由于内存和 I/O 子系统的关连性,因此它是非常重要的。例如,在 I/O 密集型系统中(执行大量 I/O 的系统),可以让 SQL Server 用来储存数据的内存越多,所必须执行的实体 I/O 越少。这是因为数据可以在数据快取中找到,而不是在磁盘中。SQL Server 具有一个复杂的快取系统,透过尽可能从内存中存取数据来提高系统效能,而不存取磁盘,因为存取磁盘将提供较低的效能。您可以从内存中存取的数据越多,您的系统效能越好,这是因为执行的实体 I/O 越少。内存存取要比实体磁盘存取快得多。
在一些情况下,内存数量的不足可能导致明显的磁盘瓶颈。这是因为系统无法有效地进行快取将导致更多的实体磁盘 I/O 操作。要看 SQL Server 正在使用多少系统内存,就用系统监视器来检查 SQL Server:Memory Manager 物件中的 Total Server Memory (KB)计数器。如果 SQL Server 没有用到如您预期的内存大小,也许就要调整内存的参数设定(如本章稍后 <SQL Server组态设定> 一节所述。)。
要确定您是否有足够的快取数量,请使用效能监视器来检查 SQL Server:Buffer Manager 物件中的 Buffer Cache Hit Ratio 计数器。通常的规则是您需要有 90% 或更高的快取命中比率。如果这个命中比率低于 90%,请增加更多的内存。注意,在一些情况下,您的系统无法达到 90% 的快取是由于应用程序的特性。这可能是因为相同的数据分页很少被重新使用,而系统又频繁地刷新快取中旧的数据分页以存入新的资料分页。
________________________________________
说明
SQL Server 2000 根据系统可用内存和内存参数设定,动态地为缓冲快取分配内存。一些外部资源(例如打印程序和其它的应用程序等)可能导致 SQL Server 释放大部分的内存来为其它程序使用。仔细监控系统内存,如果可能的话,请将 SQL Server 分隔在它自己的系统中。关于使用内存参数的详细说明,请参阅 第 30 章 以及本章后面的 < SQL Server组态设定 > 一节。
________________________________________
I/O 子系统
 
在 I/O 子系统中的瓶颈是数据库系统中最容易发生的硬件问题。它仅次于撰写拙劣的 SQL 陈述式,拙劣的 SQL 陈述式是最大的效能问题。幸运的是,I/O 子系统也是最容易解决的效能问题之一。在很多情况下,增加磁盘可以完全消除这个效能瓶颈。
I/O 子系统问题来自于磁盘只能以特定速率工作的事实。例如,一个磁盘可能具有每秒85次 I/O 的处理能力。如果磁盘负荷过多,那么这些磁盘的 I/O 会产生队列,而 SQL Server 将遇到较长的 I/O 等待时间。这些较长的 I/O 等待时间可能导致过长时间的锁定占有,或执行绪在等待资源时处于空闲状态。最终结果将是整个系统的效能受损,进而导致愤怒的使用者抱怨他们的交易使用太长的时间。
在大多数情况下,I/O 子系统效能问题的发生是因为 I/O 子系统没有正确的规划它所执行的负载。关于规划的主题在 第 5 章 和 第 6 章 中已详细讨论,但让我们在这里简单的回顾一下。
大小的规划是必须的,因为单一磁盘每秒可以执行 I/O 次数受到限制。当交易记录文件执行多数循序性 I/O 时,就会像交易记录文件一样,磁盘可能达到每秒 150 次 I/O 而不会负载过量。另一方面,当数据文件执行随机性 I/O 时,就像数据文件一样,相同的磁盘可能只有每秒 85 次 I/O。如果系统需要执行更高的 I/O,那么等待时间将变得很长。
要确定是否过度使用磁盘驱动器,请使用效能监视器对象 PhysicalDisk 和 LogicalDisk监控计数器(稍后将在本节中讨论)。计数器收集关于实体和逻辑磁盘 I/O 行为的数据,例如每秒磁盘中发生的读取和写入。您必须使用 Windows NT/2000 指令 DISKPERF 启动磁盘效能计数器。这些计数器在安装操作系统时可用,但您应该知道如何启动与关闭计数器。计数器在收集数据时会占用系统资源,如 CPU 的时间,因此您应该只在要监视系统 I/O 时使用它们。您可使用 Windows NT/2000 指令 DISKPERF 来启动或关闭计数器。
要知道 DISKPERF 是否启动,请在命令提示字符下键入下列指令:
diskperf
如果 DISKPERF 已经启动,您将看到这个讯息:"本系统的实体磁盘效能计数器已设为启动"。如果 DISKPERF 没有开启,您将看到这个讯息:"本系统的逻辑和实体磁盘效能计数器现在设定为不启动。"
要启动 DISKPERF,请在命令提示字符下键入下列指令:
diskperf -Y
要停用 DISKPERF,请执行该指令:
diskperf -N
在 DISKPERF 生效前,您必须重新启动计算机。键入下面指令来看更多的DISKPERF 选项:
diskperf ?
有特殊重要性的计数器是 Disk Writes/Sec、Disk Reads/Sec、Avg. Disk Queue Length、Avg. Disk Sec/Write和Avg. Disk Sec/Read。这些计数器可以帮助您确定磁盘子系统是否过度使用。PhysicalDisk 和 LogicalDisk 对象都提供这些计数器。如果要详细检视这些计数器提供的信息,当增加计数器时,请在 新增计数器 对话框中按一下 说明 。
我们来看一个使用计数器的例子。假设您的系统有一个 I/O 瓶颈,您将检查PhysicalDisk 对象中的 Avg. Disk Sec/Transfer、Avg. Disk Sec/Read和Avg. Disk Sec/Write 计数器,因为它们监视磁盘需要执行读写的时间量,过长的等待时间表示您过度使用磁盘驱动器或磁盘阵列。一般的规则是这些计数器的正常读数在千分之 1 到 15 秒(0.001到0.015)之间,但是在尖峰时期可能达到千分之 20 秒(0.020)。如果您观察到高于千分之 20 秒的数值,您可能会遇到一个 I/O 子系统效能问题。
同时也检查 Disk Writes/Sec 和 Disk Reads/Sec。让我们假定这些值计数器显示每个磁盘每秒 20 次写入和 20 次读取,总共 40 次 I/O,且容量为每秒 85 次 I/O。同时如果您的磁盘等待时间较长的话,磁盘驱动器就可能故障了。另一方面,如果磁盘执行每秒 100 次 I/O,且等待时间大约千分之 20 秒或更多,则您需要增加磁盘来提高效能。
使用 RAID 数组时,如果您想确定您的系统正在执行的 I/O 有多少的话,就将在效能监视器中看到的每秒 I/O 次数除以数组中磁盘的总数量和 RAID 资源占用的因子。下表列出了使用 RAID 技术时产生读写的实体 I/O 次数。
表36-1 每个RAID层级读写执行的实体I/O次数
RAID层级  读取  写入
0 1 1
1或10 1 2
5 1 4
一般情况下,更正 I/O 子系统瓶颈的最佳途径是增加更多的磁盘。但是请记得考虑 I/O 瓶颈的其它可能原因,例如较低的快取命中速率以及执行交易的 I/O 太多。(在大多数情况下,快取命中速率低于 90% 就太低了。)如果您发现了一个 I/O 瓶颈,请回顾 第 6 章 中的说明,来确定您系统需要的磁盘数量。
故障组件
 
有时您的系统可能遇到由故障组件引起的效能问题。如果故障组件没有完全失效而仅仅是效能降低,那这可能是一个很难排除的问题,因为问题的多样性和复杂性以及它的解决方案已经超出了本书的范围。但是这里有几个辨识故障组件问题的诀窍:
•  比较磁盘和数组 当在效能监视器中检视统计资料时,比较相似的组件。如果您发现两个磁盘执行 I/O 的速率相同,却显示不同的等待时间,那么较慢的磁盘可能遇到了问题。
 
•  监控指示灯 网络集线器通常有碰撞指示灯。如果您注意到某个网络区段出现了异常的高碰撞,这时您可能有故障组件,也许是网络卡或是网络缆线。
 
•  了解您的系统 您花在系统上的时间越多,您越能了解系统的特性。当系统不正常运作时您就会发现。
 
•  使用效能监视器 这是一个监控系统行为的好方法。
 
•  阅读记录文件 养成常常检查 SQL Server 和 Windows2000 事件检视(Event Viewer)系统和应用程序记录的习惯。每天回顾这些记录文件可以在问题失控前发现问题。
 
应用程序
 
造成效能问题的另一个系统组件是 SQL Server 应用程序。这些问题可能发生在应用程序代码或在应用程序执行时的 SQL 陈述式中。本节提供一些提示和准则,用来解决和 SQL Server 应用程序有关的效能问题。
最佳化执行计划
 
正如我们在 第 35 章 所看到的,选择一个最佳的执行计划和数据存取方法对于查询是很重要的。不幸的是,并没有一定的公式来确定最佳的计划。SQL Server 自动选择查询最佳化器的计算为最佳的执行计划。随着您熟悉联结操作的不同类型,您可能可以透过分析以确定最佳执行计划。通常您需要试过各种不同的计划后,才能找到最佳方法。
使用索引
 
正如我们在 第 17 章 和 第 35 章 所看到的,正确索引的使用对于好的效能是十分重要的。使用索引来找出所需的数据,这只需要 10 到 20 个 I/O 操作,而透过数据表扫描找出所需的数据,则可能需要成千上万的 I/O 操作。不过必须谨慎地使用索引。记住,在使用 INSERT、UPDATE 或 DELETE 陈述式修改数据表的各种数据时,索引将自动更新,显示更改后的数据,因此会产生比平常更多的 I/O 操作。注意不要建立太多索引,否则用来维护这些索引的资源占用可能会影响数据修改的效能。
使用预存程序
 
正如我们在 第 21 章 中所看到的,预存程序被用来在服务器上执行预先包装和预先编译的SQL陈述式。从应用程序呼叫预存程序对效能有所帮助,因为改善了服务器上 SQL 陈述式的可重复使用性,也减少了网络的流量。由于预存程序执行在服务器上,可以减少客户端和服务器之间传送的数据数量,您可以在预存程序中将程序程序化并将数据筛选处理,而不用在应用程序中执行这些动作。
SQL Server 组态设定
 
SQL Server 2000 使用虚拟方式自行调整组态,但是有些调整参数仍然可以用来变更您的系统操作和执行的方式。在本节中,您将学到如何设定这些选项,以及它们如何影响到您系统的操作。在大多数情况下,是不需要更改这些参数的,但是了解它们是什么以及它们做什么使您有机会决定是否更改它们。您可以使用 Enterprise Manager 或 sp_configure 来设定。
要使用 Enterprise Manager,请在您要设定的服务器名称上按右键并从快捷菜单中选择 内容 ,显示 SQL Server属性 窗口。这个窗口包含9个页签,每个页签都有您可以设定的选项。下面将说明这些页签以及它们的选项。
当使用 sp_configure 设定这些选项时,某些选项是设定为进阶(advanced)的。(下面几节将说明哪些是进阶选项。)您必须将 show advanced options 选项设定为1(启用),这样才可以使用 sp_configure 来更改一个进阶选项。预设情况下该选项设定为0(禁用)。(当使用 Enterprise Manger 来设定进阶选项时,您不需要担心这个选项。)要设定 show advance options,请使用下面的陈述式:
sp_configure "show advanced options", 1
GO
通常,要使用 sp_configure 设定某个选项,请使用下面的语法:
sp configure "option name", value
affinity mask 选项
 
affinity mask 选项是用来指定在多处理器环境中,SQL Server 执行绪可以在哪些CPU 上执行。默认值为0,指定由 Windows 2000 排程算法来决定执行绪关连性。非零值设定了一个 bitmap,用来定义可以执行 SQL Server 的 CPU。十进制数值1(或二进制位屏蔽值00000001)指明只使用CPU 1、2(或00000010)指明只使用CPU 2、3(或00000011)指明使用CPU 1和CPU 2,等等。
这个选项是进阶选项,表示在使用 sp_configure 设定该选项时,必须设定 show advanced options 为1。它也可以用 Enterprise Manager 来设定。要这样做,请选择 SQL Server属性 窗口中的 处理器 页签,在 处理器控制 区域,选择您要 SQL Server 使用的 CPU 旁的复选框。按一下 套用 和 确定 来储存更改。您必须停止并重新启动 SQL Server,使该更改生效。
在指定的 SQL Server 系统上,您必须设定 affinity mask 选项,允许 SQL Server使用所有的 CPU。在没有指定的 SQL Server 系统上(包括需要 CPU 时间的其它处理程序),您可能要试着设定 affinity mask,这样 SQL Server 才会留下一个 CPU 不用而用其余的 CPU。
lightweight pooling 选项
 
lightweight pooling 选项用来设定 SQL Server 使用 lightweight 执行绪或细微模式(fibers)。使用细微模式可以减少内容切换(context switches),允许 SQL Server(而不使用 Windows NT 或 Windows 2000 的排程程序)掌控排程。如果您的应用程序在多处理器系统中执行,且您看到了大量的内容切换,您可能需要将 lightweight pooling 参数设定为1,这将启用 lightweight pooling,然后监控内容切换的数量,来核对它们是否已经减少了。默认值为 0,这样会禁用细微模式。
lightweight pooling选项也是一个进阶选项,在使用sp_configure 设定该选项时,必须将show advanced options设定为1。它也可以用Enterprise Manager来设定。选择 SQL Server属性 窗口中的 处理器 页签,在 处理器控制 区域,选取 使用Windows NT Fibers 复选框来启用该选项,或者清除这个复选框来禁用该选项。按一下 套用 ,按一下 确定 ,然后停止并重新启动SQL Server以使该选项生效。
max server memory选项
 
SQL Server 动态地分配内存。要指定 SQL Server 分配给缓冲集区的最大内存数(单位为MB),您可以设定 max server memory 选项。因为 SQL Server 需要一些时间来释放内存,所以如果您有其它的应用程序定期的需要内存,那么应该设定 max server memory,这样 SQL Server 就会为其它应用程序保留一部分内存。默认值为 2147483647,这表示 SQL Server 请求系统能尽量提供内存,而当其它应用程序需要内存和释放内存时,动态地分配和解除分配内存。建议在 SQL Server 系统中使用这个设定。如果您要更改这个设定,请计算您可以给 SQL Server 的最大内存数量,从全部的物理内存中减去 Windows 2000 需要的内存加上其它非 SQL Server 使用需要的内存。
这是一个进阶选项,在使用 sp_configure 设定该选项时,show advanced options 必须被设定为1。要使用 Enterprise Manager 来设定该选项,在 SQL Server 属性 窗口中选择 内存 页签,并调整 最大值(MB) 滑动杆。接着按一下 动态设定SQL Server的内存 。这个选项的更改将立即生效,不需要停止并重新启动 SQL Server。(如果按一下 使用定量的内存 ,您就能设定内存的固定值。这可以限制 SQL Server 分配内存的量,而在内存分配到固定值后,不再释放内存。)
min server memory 选项
 
min server memory 选项指定分配给 SQL Server 缓冲集区的最小内存数,单位为 MB。在 SQL Server 为其它应用程序保留过多内存的系统中,设定这个参数将很有用。例如,服务器当成数据库服务器的同时,还用作打印和档案服务,在这种环境中,SQL Server 可能释放太多的内存给这些其它的应用程序。这样会减慢使用者的响应时间。
min server memory 的默认值为0,允许 SQL Server 动态的分配和解除分配内存。建议使用这个设定,但是如果您的服务器不只用作 SQL Server,可能就需要更改这些设定。
这是一个进阶选项,在使用 sp_configure 设定该选项时,show advanced options 必须被设定为 1。您可以使用 Enterprise Manager 来设定该选项,请在 SQL Server 属性 窗口中选择 内存 页签,调整 最小值(MB) 滑动杆,并按一下 动态设定SQL Server的内存 。这个选项的更改将立即生效,不需要停止并重新启动 SQL Server。
recovery interval选项
 
recovery interval 选项定义了系统在故障事件中回复的最大时间,单位为分钟。SQL Server 使用这个设定以及内建的算法,决定执行自动检查点的频率,这样回复工作将在指定的分钟数内完成。根据在系统中有多少工作发生,SQL Server 决定两次检查点之间应该有多久的间隔时间。如果有很多工作要执行,检查点执行的频率将比平常多。执行的工作越少,从失效回复的时间越少。另外,回复间隔越长,检查点间允许的间隔时间越长。
透过减少检查点数量来增加回复间隔将提高效能(由于检查点导致大量的磁盘写入,这将使使用者交易时间慢几秒钟),但它也增加了回复 SQL Server 所需要的时间。默认值为 0,指定 SQL Server 确定间隔-大约1分钟的回复时间。增加 recovery interval 选项是有风险的。通常使用 5 到 15 分钟的值,但这完全取决于您在系统失效时是否能冒等待 5 到 15 分钟的风险来等待数据库的回复。一般说来,您可能要增加 recovery interval,以减少每个检查点的频率以及它们大量的写入,因此允许使用者在 I/O 子系统中更自由的执行他们的交易,而不会中断。
这是一个进阶选项,在使用 sp_configure 设定该选项时,show advanced options 必须被设定为 1。要使用 Enterprise Manager 设定这个选项,请在 SQL Server 属性 窗口中选取 数据库设定 页签,并在 复原间隔(分钟) 文字方块中键入一个值。这个选项的更改将立即生效,不需要停止并重新启动 SQL Server。
本章总结
 
在本章中,您学到了成为 DBA 将遇到的一般效能问题。您也看到如何使用系统监视器和 Enterprise Manger 来监控系统,并帮助定位效能瓶颈。另外您还学到了如何检测以及解决一般系统效能问题。
本书让您学习如何管理 SQL Server 2000、何谓管理 SQL Server 2000 和为什么要管理 SQL Server 2000。您现在应该可以有效的管理和调整您的 SQL Server 系统了,并能够顺利有效地执行日常管理任务。我们希望您能够喜欢阅读这本书,就像我们在写作本书时获得乐趣一样。




35. 使用SQL Query Analyzer和SQL Profiler
使用SQL Query Analyzer
使用SQL Profiler
最佳化T-SQL陈述式
本章总结
本章我们将继续 第 21 章 中关于预存程序的说明。本章将学习如何利用 SQL Query Analyzer 和 SQL Profile 分析预存程序和其它陈述式。从分析中可以确定 T-SQL 陈述式是否有效率。一个有效的 SQL Server 查询会使用适当的操作次序和适当的索引,来减少过程的行列数并使 I/O 操作数达到最小。
用 Query Analyzer 可以检视 SQL Server query optimizer 为 T-SQL 陈述式选择的执行计划。query optimizer 是用来为每个 T-SQL 陈述式找寻最佳执行计划的模块。query optimizer 分析每个 T-SQL 陈述式,考虑大量可能的执行计划,并根据所需要的资源和程序时间来计算每个计划的资源消耗。选择最不会消耗资源的计划。每个计划的资源消耗决定于系统收集关于数据的统计结果,但这些资料不一定是最新的。因为您可能比 query optimizer 更了解数据库和数据内容,所以能够决定比 query optimizer 更好的计划。使用 Query Analyzer 提供的信息,可以决定 query optimizer 提供给陈述式的计划是否有效率。如果确定它不够好,就试着修改 T-SQL 陈述式或用 SQL 提示将陈述式最佳化。本章将学习如何使用 Query Analyzer,以及如何最佳化 T-SQL 陈述式。
使用 Profiler 可以分析 SQL Server 系统内部活动,以确定哪些 SQL 陈述式和预存程序的使用造成系统资源的负担。有了这项信息,就能先调整这些陈述式和预存程序。本章除了学习如何使用 Profiler 外,也将说明如何最有效地使用 Profiler 提供的信息。
使用 SQL Query Analyzer
 
Microsoft SQL Server 2000 提供的 Query Analyzer 工具,取代 Windows (ISQL/W)中的 Interactive SQL 成为 SQL 图形接口。然而您可能注意到 Query Analyzer 显示在任务管理员中的是 isqlw.exe。可以用 Query Analyzer 来处理 T-SQL 陈述式,并检视这些陈述式的结果。Query Analyzer 也可以被当作除错工具,用于评估 query optimizer 为 T-SQL query optimizer 陈述式所产生的执行计划。
执行 T-SQL 陈述式
 
Query Analyzer 最基本的功能是执行 T-SQL 陈述式,并显示陈述式结果。依照下列步骤用 Query Analyzer 来执行 T-SQL 陈述式:
1. 点选 开始 / 程序集 / Microsoft SQL Server / Query Analyzer ,会显示联机到SQL Server 对话框,如图35-1所示。利用这个对话框和 SQL Server 系统联机。
 
 
图35-1 联机到 SQL Server 对话框
2. 在 SQL Server 文字方块中键入服务器名称。可以是本地服务器或远程服务器的名称。选一个想要连接的本地服务器,会显示如图35-1中的黑点。SQL Server 之下的复选框,可指定系统未运作时是否要开启服务器。在 联机使用 区域中选择用来联机 SQL Server 的验证方式。如果选择使用 Windows 的账户验证,就不必指定使用者名称或密码,因为 Windows 2000 的账号会被用于验证存取 SQL Server 上。如果选择使用 SQL Server 的账户验证,就必须指定 SQL Server 使用者名称和密码,才能存取 SQL Server。
3. 按一下 确定 ,联机到指定的 SQL Server 上,并启动 Query Analyzer。当Query Analyzer 窗口出现时,只能看到 Query 和巡览窗格,但是一旦开始传送 T-SQL 陈述式,窗口就会变更。最大化 Query 窗格会填满整个 Query Analyzer 窗口,如图35-2所示。在工具列的下拉式清单中选取所要执行查询的数据库。图35-2显示选择 master 数据库,本范例中会在下拉式清单中选取 Northwind 数据库。
 
 
图35-2 SQL Query Analyzer 窗口
4. 选择数据库之后,在右边窗格中键入 T-SQL 陈述式,在这个范例中,请键入『SELECT * FROM customers』。现在有多个选项可用,可以按一下工具列上的 剖析查询 按钮(蓝色的查核记号)来检查 T-SQL 陈述式的语法,或者按一下 执行查询 按钮(朝右的绿色三角形)来执行陈述式。按 取消查询执行 按钮(正方形)可停止查询的执行。图35-3显示了对 Northwind 数据库的 customers 数据表的完整查询。
一旦传送了 T-SQL 陈述式,Query Analyzer 将建立一个窗格,让您可以垂直和水平的卷动来检视结果,如图35-3所示。Query Analyzer 还可以用来帮助您调整您的 T-SQL 陈述式,您将会在本章的 <最佳化T-SQL陈述式> 一节中看到。

 
 
图35-3 完整的 Query Analyzer 查询
检视执行计划和修改 T-SQL 陈述式
 
Query Analyzer 也可以用来检视执行计划,这个执行计划是 Query Optimizer 为您的 T-SQL 陈述式所做的选择。这个特性可帮助您判断 T-SQL 陈述式是否有效率,并确定应该选择哪条执行路径和数据存取路径。然后您可以修改 T-SQL 陈述式和数据库架构,检查效能是否得以提高。要使用 Query Analyzer 来检视 T-SQL 陈述式的评估执行计划,请按照下列步骤操作:
1. 在 Query Analyzer 窗口键入需要 Query Analyzer 评估的 T-SQL 陈述式后,按下 显示评估的执行计划 按钮(这个按钮在数据库选择下拉式清单的右边),或者按Ctrl+L,显示 评估的执行计划 窗格,如图35-4。在这个窗格中,查询透过图形来描述,每个操作的消耗与资料存取的方法都在此显示。在图35-4的窗格中,出现索引名称 Customers.PK_Customers,表示丛集索引 Customers.Pk_Customers 被用来存取资料。
 
 
图35-4 评估的执行计划窗格
2.  评估的执行计划 窗格中还提供其它附加数据。要检视操作的附加数据,请将鼠标光标移动到操作图标上。就会出现一个弹出窗口,其中包含附加数据,如图35-5所示。
 
 
图35-5 检视关于操作的附加数据
这个弹出窗口包含下列信息:
o  实体作业 查询所执行的操作,例如索引扫描、联结和总计等等。如果实体操作被显示为红色,那是 Query Optimizer 发出的警告,这时您应该固定 T-SQL 陈述式。
 
o  估计的数据列记数 预估由操作检索的列数。
 
o  估计的数据列大小 需要检索的列的估计大小。
 
o  估计的I/O耗用/估计的CPU耗用 由该操作占用的估计 I/O 资源和 CPU时间。越低的值意味着该 T-SQL 陈述式越有效率。
 
o  估计的执行数 该操作在 T-SQL 陈述式中执行的次数。
 
o  估计的耗用 由 Query Optimizer 决定的操作消耗。这个消耗显示为T-SQL 陈述式的总消耗百分数。
 
o  估计的子树耗用时间 执行前面部分和这一部分 T-SQL 陈述式的消耗。如果存在多个子树,这个选项允许您检视执行每个子树的消耗。
 
o  自变量 T-SQL陈述式使用的自变量。
 
________________________________________
说明
执行计划(execution plan)描述了 Query Optimizer 如何选择执行 T-SQL 陈述式,并包括步骤的次序和所使用的操作类型。数据存取方法(Data Access Method)是描述数据库对象(数据表、索引等)如何被存取的一种对象。这两者是相关联的,因为在有些时候,数据存取方法被考虑为执行计划的一部分。当然也可以单独的考虑。
________________________________________
接下来将看到使用 Query Analyzer 较为复杂的范例。范例显示低效率的 T-SQL陈述式对效能的影响:减慢响应时间,并占用其它程序的系统资源。现在先看一个使用 Query Analyzer 检视和修改 T-SQL 陈述式执行计划的范例。修改 T-SQL 陈述式能达到较好的效能。在许多情况下,可以建立更有效、功能更佳的 T-SQL 陈述式。接下来会说明几种 T-SQL 陈述式,它们属于较复杂的预估执行计划类型。
这些范例使用 Northwind 数据库中的 Orders 数据表。现在来检视这个数据表的组织。这个信息会帮助确定 Query Optimizer 是否选择了适当的执行计划。Orders 数据表在 OrderID 一栏中有一个名为 PK_Orders 的丛集索引,另外还有八个其它的索引,如图35-6中的 Manage Indexes 对话框所示。(要存取这个对话框,请在 Enterprise Manager中,展开一个服务器组,展开一个服务器,展开 数据库 数据夹,展开 Northwind 数据库,然后选取 数据表 数据夹。在右侧窗格中的 Orders 数据表上按鼠标右钮,并从快捷菜单中选择 所有工作 ,接着选择 管理索引 。或者只要从 Query Analyzer 工具 菜单中直接选择 管理索引 ,接着从下拉式菜单中选择 Orders 数据表。)

 
 
图35-6 管理索引对话框
检视计划和修改 SELECT 陈述式
 
本节中,这个查询的范例要求获得关于订单的信息,这些订单是由职员 ID 为 4的职员储存的。请在 Qery Analyzer 输入以下查询,并执行 显示评估的执行计划 :
SELECT OrderID, CustomerID, EmployeeID, OrderDate
FROM orders
WHERE EmployeeID = 4
在该职员的组织中,每个职员处理订单的一小部分,因此可能需要 SQL Server在进行查询时使用 EmployeeID索引。但是,Query Analyzer 显示的却是 SQL Server 使用的存取方法是 PK_Orders 丛集索引,如图35-7中的 评估的执行计划 窗格所示。

 
 
图35-7 评估的执行计划窗格显示了使用 PK_Orders 丛集索引。
要 Query Optimizer 使用 EmployeeID 索引,可以使用 SELECT 陈述式的提示(hint),程序代码如下(提示将在本章的 <使用提示> 一节中讨论。):
SELECT OrderID, CustomerID, EmployeeID, OrderDate
FROM orders WITH (INDEX ( EmployeeID))
WHERE EmployeeID = 4
________________________________________
说明
在 SQL Server 7 中,较好用的索引提示是 INDEX=index_name。
在 SQL Server 2000 中,较好用的索引提示是 INDEX(index_name)。
________________________________________
透过这个信息,可以指示 Query Optimizer 使用所需要的执行计划,而不是 Query Optimizer 选择的计划。调整过的评估执行计划窗格如图35-8所示。可以从显示的数据存取方法中看到,使用的是 EmployeeID 索引,然后传回一个书签搜寻(bookmark lookup),该查询将获得来自数据库的数据。(书签搜寻搜索一列数据的内部识别码。)

 
 
图35-8 调整过后的评估执行的计划窗格
Query Optimizer 是一个有效率的工具,以不断的更新统计数据,提供选择最佳的执行计划。由于不同的公司行号可能更清楚自己的组织和数据,所以某些情况下,公司可以选择比 Query Optimizer 更有效率的最佳执行计划。
________________________________________
注意
使用提示代替 Query Optimizer 的选择时,必须承担变更可能带来的风险。虽然数据遗失或损毁的机率不大,不过可能对系统的执行效能产生的是负面的影响。
________________________________________
检视联结操作
 
执行联结操作比执行选取操作多出了更过的执行过程,稍后会在评估执行的计划窗格中看到。联结操作会对数个数据表进行存取的动作,并在存取后组合所搜寻的数据。(联结在 第 14 章 中讨论)。请在 Query Analyzer 输入以下的联结操作范例:
SELECT OrderID, CustomerID, Employees.EmployeeID, FirstName,
     LastName, OrderDate
FROM Orders Join Employees ON Orders.EmployeeID = Employees.
EmployeeID
之前的陈述式包括 SQL-92 JOIN 操作元。建议使用此操作元在 SQL Server 2000中执行连结。下面的陈述式使用较传统的连结语法:
SELECT OrderID, CustomerID, Employees.EmployeeID, FirstName,
     LastName, OrderDate
FROM Orders, Employees
WHERE Orders.EmployeeID = Employees.EmployeeID
T-SQL 陈述式在 EmployeeID 资料行中联结了 Orders 和 Employees 资料表。评估执行计划结果如图35-9所示。

 
 
图35-9 显示在评估执行的计划窗格的联结操作
在窗格中可以看到两个子树中哪个的消耗较大,也可以看到规划联结操作的类型。SQL Server 支持多种不同的联结操作,包括杂凑联结(hash join)、巢状循环联结(nested loops join)和合并联结(merge join)。复杂的联结操作,执行计划会相对的变得复杂。由于您的目的是要减少占用 CPU 时间总量,以及减少执行 I/O 操作的数目,所以必须判断是否使用了好的执行计划。有时可以使用提示来指定需要使用的特殊索引,从而减少 CPU 和 I/O 行为。在这个查询中,由于联结是指定在 WHERE 子句中的唯一操作,这个执行计划应该是最适合的。
检视总计操作
 
下面显示的 T-SQL 陈述式执行连结操作和总计操作,请在 Query Analyzer 中输入:
SET QUOTED_IDENTIFIER ON
GO
SELECT CustomerID, SUM("Order Details".UnitPrice)
FROM Orders JOIN "Order Details" ON Orders.OrderID = "Order
Details".OrderID
GROUP BY CustomerID
________________________________________
说明
因为数据表名称 Order Details 包含了一个关键词和一个空格,所以必须使用选项 SET QUOTED_IDENTIFIER ON。要获得更多关于这个选项的信息,请参阅《在线丛书》索引中的 SET QUOTED_IDENTIFIER。
________________________________________
这个复合操作的评估执行的计划窗格显示在图35-10。

 
 
图35-10 显示在评估执行的计划窗格中的总计操作
检视预存程序
 
要显示预存程序的执行计划,可以简单的在 Query Analyzer 中呼叫预存程序。Query Analyzer 会显示所呼叫预存程序的评估执行计划,如图35-11所示的 sp_who。(需要注意的是,预存程序的执行计划相当复杂)。即使不确定组成预存程序的 T-SQL 陈述式,也可以显示该预存程序的执行计划。

 
 
图35-11 在评估执行的计划窗格中的预存程序
使用对象浏览器
 
对象浏览器(Object Browser)包含在 SQL Server 2000 中,用来提升 Query Analyzer 的功能。启动 Query Analyzer 时,会在左边窗口看到 对象浏览器 。 对象浏览器 分成数据库对象区和通用对象区两部份。在数据库对象区,可以浏览像数据表和检视表等对象;在通用对象区,可以存取系统对象和菜单。可以利用 物件浏览器 找出所提供的信息后,然后决定用的信息。
数据库对象
 
 对象浏览 顶端部份含有数据库对象,可以立即看到预设数据库以及所建立的数据库,并显示所属的 SQL Server。想要知道在 对象浏览 之中有哪些可用信息,只要展开对象即可。先展开 Northwind 数据库,然后展开 使用者数据表 。现在可看到 Northwind 数据库中可用的数据表,如图35-12所示。

 
 
图35-12 检视对象浏览中的数据表
接着展开一个使用者定义数据表,然后展开包含关于字段、索引、条件约束、资源依存性、触发程序信息的数据夹。图35-13显示展开的 Orders 数据表。或者可以展开数据夹,检视关于系统数据表、检视表、预存程序、功能和使用者定义数据类型的信息。
在 Query Analyzer 中提供对象信息,是相当方便的,这样在建立 SQL 陈述式和预存程序时,就不需要再检查 Query Analyzer 以外的对象信息。不但可以在 对象浏览 中检视信息,还可以编辑对象、拖曳对象,甚至可以建立指令码和修改对象,将功能加在一个已经很实用的工具中。

 
 
图35-13 展开在对象浏览中的数据表
通用对象
 
在 对象浏览 较下面的部份是名为通用对象(Common Objects)的数据夹,这个数据夹中包含了如设定功能、光标功能、日期和时间功能以及数学功能等对象信息的数据夹。因此您可以很快地存取一个要使用的功能而不须查询语法。在这个区域展开数据夹的话,将显示设定选项,如图35-14所示。将这些功能拖曳到 Query 窗格中,或者用鼠标点选这个功能以显示一个简要描述。这对于 ad-hoc 查询过程是相当方便的。

 
 
图35-14 在对象浏览的通用对象中展开一个数据夹
除了存取全域变量之外,您还可以存取很多其它有用的快捷菜单,如数学和字符串功能。继续展开对象,您可以用这些菜单得到参数要求的信息。例如,图35-15显示展开 数学函数 中的 参数 数据夹。

 
 
图35-15 检视对象浏览中的参数数据夹
使用SQL Profiler
 
除了 Query Analyzer 以外,SQL Profiler 工具也可以帮助找出低效率的 T-SQL陈述式。Profiler 可以显示所有系统中执行的 T-SQL 陈述式,并用图形加以显示。您也可以使用多种排序和筛选选项,找出使用了最多 CPU 和 I/O 资源的 T-SQL 陈述式。有了这些信息就可以确定在调整系统时需要集中焦点在哪些 T-SQL 陈述式上。对于透过应用程序呼叫的 T-SQL 陈述式,可以检视 T-SQL 陈述式,并决定利用存取应用程序来源程序代码时的效率如何。
SQL Server 2000 中的 Profiler 工具类似 SQL Server 7 中的 Profiler 工具,当然有些加强的功能。其中一项新功能是引用追踪模板,用来建立追踪档案。(在确定能够使用这个功能追踪 SQL Server 之后,追踪才能建立)。在 SQL Server 7 中,追踪功能只能以手动建立。
要呼叫 Profiler 工具并执行追踪,请遵循下列步骤:
1. 按一下 开始 / 程序集 / Microsoft SQL Server / Profiles 。在 Profiler 刚出现时,会看到一个空的 Profiler 窗口。在 Profiler 中如果没有打开任何窗格,就不会剖析任何陈述式。
2. 要开始分析,必须选择已存在的追踪模式,或是建立一个新的追踪模式。(启动过程将在步骤4介绍)。SQL Profiler 提供数种追踪模式。使用这些功能由于不必从 scratch 建立追踪,因此节省不少时间。要检查追踪清单,请在 档案 菜单中点选 开启旧档 ,选择 追踪模板 ,显示 开启旧文件 对话框,如图35-16所示。
 
 
图35-16 开启旧文件对话框中显示可用的追踪
SQL Server 中的追踪描述如下:
o  SQLServerProfilerSP_Counts.tdf 统计已经执行预存程序的数量。这个结果将根据预存程序的名称进行分组,其中包括程序所执行的次数。
 
o  SQLServerProfilerStandard.tdf 收集关于连结点的信息,执行预存程序,以及依序执行 SQL 批次檔。
 
o  SQLServerProfilerTSQL.tdf 收集所有的 T-SQL 陈述式传送至 SQL Server 的次序且依使用者团体分类传送。这个追踪包含了 T-SQL 陈述式以及它所执行的时间。
 
o  SQLServerProfilerTSQL_Duration.tdf 显示执行的 T-SQL 陈述式,以及这些 T-SQL 陈述式执行所用的时间(一千分之一秒为单位)。
 
o  SQLServerProfilerTSQL_Grouped.tdf 收集与 SQLServerProfilerTSQL 追踪类似的数据,但是根据传送陈述式的使用者来将数据分组。
 
o  SQLServerProfilerTSQL_Replay.tdf 提供关于已经执行的 T-SQL 陈述式的详细信息。该追踪提供可以用来重新执行 Query Analyzer 中 T-SQL 陈述式的数据。
 
o  SQLServerProfilerTSQL_SPs.tdf 显示预存程序以及预存程序中的 T-SQL指令。该结果根据陈述式执行的时间依序显示。
 
o  SQLServerProfilerProfilerTuning.tdf 收集关于预存程序和执行 SQL 批次文件的数据。
 
这些追踪相当有用。例如 SQLServerProfilerTSQL_Duration 追踪可找出哪些T-SQL 陈述式花费了大量的执行时间。这些信息使您可以开始最佳化查询。一个陈述式执行得很慢,可能是因为它的工作量很大,或者效率很低。在下一个步骤中将说明,必须使用每个追踪的预设定义。
3. 要启动追踪,请选取 档案 / 新增 ,接着选择 追踪 。显示 联机到SQL Server 对话框,如图35-17所示。在这个对话框中,选择要追踪的 SQL Server 系统,然后按 确定 。
 
 
图35-17 联机到SQL Server对话框
4. 进入 追踪属性 窗口,如图35-18所示。在 一般 页签,可以命名并选择追踪的起始点。本范例是选择 SQLServerProfilerTSQLDuration 追踪。在页签下面的部份,可以指定是否要将获得的追踪内容输入到档案或 SQL Server 数据表中。如果没有选择这些选项,那么追踪将只在屏幕上出现。另外,可以指定追踪完成的时间,这在执行长时间追踪时相当有用。
 
 
图35-18 追踪属性窗口的一般页签
5. 接着选择 事件 页签,如图35-19所示。这里可以选取一个或多个追踪记录的事件。大量的类型和特殊的事件可以被追踪,列在 可用的事件类别 清单中的数据均可追踪。
 
 
图35-19 追踪属性窗口的事件页签
6. 选择要追踪的事件后,点选 数据行 页签,如图35-20所示。在这个页签中,指定在追踪过程中要收集哪些数据。这个数据包括终止时间、对象 ID 等等。
 
 
图35-20 追踪属性窗口的数据行页签
7. 选取 筛选器 页签,如图35-21所示。这个页签中可以指定是否要撷取事件所需的条件。例如,排除追踪 Profiler(默认值)。透过排除 SQL Server 过程,可以避免 Profiler 窗口的混乱,增加阅读性。
 
 
图35-21 追踪属性窗口的筛选器页签
8. 完成设定选项后,按 执行 启动追踪。如果要修改追踪,建议使用 档案 菜单中的 另存新文件 选项来保存追踪修改(用不同的名称)。一旦开始追踪,事件将会出现在 Profiler 窗口。使用本例中所选的追踪,事件将会用 Duration 排序(千万分之一秒)。图35-22显示 Profiler 窗口执行中的追踪。
________________________________________
注意
在繁忙的环境中,Profiler 可能会使用重要的系统资源。追踪越多的事件,会占用越多的系统资源。
________________________________________
最佳化 T-SQL 陈述式
 
在前面的章节中学到了使用 Profiler 检视系统中所执行的 T-SQL 陈述式,以及利用 Query Analyzer 确定执行计划和数据存取。也可以利用修改 T-SQL 陈述式来改善效能。拥有这些工具,就有能力修改 T-SQL 陈述式,改善陈述式的执行效能。在本节中,会看到最佳化 T-SQL 陈述式的多种途径,使其能够提供更好的效能或占用更少的系统资源。

 
 
图35-22 执行中的追踪
最佳化执行计划
 
修改执行计划是相当困难的,要建立一个比 Query Optimizer 的计划更佳的执行计划更不容易。有些操作更可能在执行计划的修改中获益,它们是 JOIN、GROUP BY、ORDER BY 和 UNION。对于这些操作的修改可以容易的透过使用提示来达成,这将在稍后的 <使用提示> 一节中提到。透过更改提示和显示 Query Analyzer 的输出,可以看到获得了一个比较有效的操作。
不过,对于最佳化 T-SQL 陈述式并没有一个特定的模式。因为每个数据库都是独一无二的,且应用程序也不相同,因此修改皆根据不同的情况进行。
选择数据存取方法
 
正如本章前面所述,数据存取方法实际上就是一组对象,SQL Server 使用这些对象从数据库中获得数据。透过分析数据库和数据库中包含的数据,可以最佳化数据存取方法,减少 I/O 操作的数量。
和修改执行计划一样,修改最佳的数据存取方法也没有一定的公式。下面的指导方针有助于选择最佳的数据存取方法:
•  使用最佳的索引 为一个操作使用最佳的索引,这在获得可能的最佳效能时是必须的。对于特定操作的最佳索引是最快速的找到数据,且最少 I/O 操作的一种方法。可以利用您对数据库和数据的深入了解或使用 Query Analyzer 来确认最佳的索引。Query Analyzer 让您尝试不同的模拟状况以确定哪个索引可以传回最少的列数。(记住,Query Analyzer 只是简单的估计了所要传回的列数;要确定精确的列数,必须使用 Profiler。)
 
________________________________________
说明
正如 第 17 章 所提到的,索引对于 SQL Server 有很大的好处,但是如果使用不正确,可能会反过来影响效能。监控每个数据表的索引数目,特别是在执行了很多 INSERT、UPDATE 和 DELETE 陈述式操作的时候。太多的索引可能会导致这种类型操作的效能降低,这是由于修改索引的额外系统资源占用所引起的效能降低。
________________________________________
•  使用覆盖式索引 (covering indexes) 正如 第 17 章 所述,使用覆盖式索引可以帮助您避免额外的 I/O 步骤。不必存取底层数据表,您可以从索引中获得所需的数据。
 
•  减少传回的数据列 决定是否需要从查询传回实际需要的所有数据。修改T-SQ L陈述式,以便于只存取需要存取的数据,不要传回将被丢弃的资料列。减少从数据库中获得的数据列,这可以透过增加查询的选择性来达成。
 
使用提示
 
可以修改 T-SQL 陈述式来更改资料存取方法和执行计划,但是如果执行时不够不谨慎,反而会变更 T-SQL 陈述式的功能。较安全的最佳化 T-SQL 陈述式的方法是使用提示。提示可指定 Query Optimizer 要执行哪些操作和需要使用哪些对象。在本节中,将学习很多不同的 SQL Server 提示,以及它们的使用方法。
联结提示
 
联结提示(join hints)是用来指定 Query Optimizer 应该执行哪些类型的联结操作。(如果在查询中没有指定类型,query optimizer 会自己选一个。)在 SQL Server 中,您可以执行巢状循环联结(nested loops joins)、杂凑联结(hash joins)、合并联结(merge joins)和远程联结(remote joins)。使用下列提示指定联结的方法:
•  LOOP 指定巢状循环联结。在巢状循环联结中,将会检查外部数据表中的每一列和内部数据表中的每一列,检查值是否相等。
 
•  HASH 指定杂凑联结。在杂凑联结中,一个数据表会被重新组织为一个杂凑数据表。其它的数据表每次被扫描一列,杂凑函数就被用来搜寻相同的内容。
 
•  MERGE 指定一个排序合并联结。在排序合并联结中,每个数据表都被排序,然后按照降序每次比较一列。
 
•  REMOTE 指定远程联结。远程联结是至少有一个联结的数据表在远程。
 
看看连结提示的范例,使用我们前面的范例(请参阅本章中的 <联结操作> 一节),我们按照下列陈述式使用提示来指定一个杂凑联结:
SELECT OrderID, CustomerID, Employees.EmployeeID, FirstName,
     LastName, OrderDate
FROM Orders, Employees
WHERE Orders.EmployeeID = Employees.EmployeeID
OPTION (HASH JOIN)
________________________________________
说明
联结提示是彼此独立的-每次只能使用其中的一种。
________________________________________
如果选择使用 SQL-92 语法作为连结,您也能用提示来指定连结类型。使用SQL-92 语法,您可以重写之前的查询,如下:
SELECT OrderID, CustomerID, Employees.EmployeeID, Firstname,
     LastName, OrderDate
FROM Orders INNER HASH JOIN Employees
ON (Orders.EmployeeID = Employees.EmployeeID)
联结提示是进阶的主题,我们并不能提供使用的经验方法。有很多不同的选择特殊联结操作的原因,例如同等运算子的数目、在联结中每个数据表的大小,以及联结的多少数据表。有一种最佳的途径可以确定更改联结操作是否将提供额外的效能,就是在 Query Analyzer 中尝试每一种类型的联结,看看哪种可以提供最小的消耗。当然,Query Optimize r通常会为帮助选择最佳的联结操作。
查询提示
 
查询提示(query hints)用来指定如何执行特定的查询操作。可用的查询操作分为三类:分组(group by)、联合(union)和混杂(miscellaneous)。
 分组提示 下面的提示指定了如何执行 GROUP BY 或 COMPUTE 操作:
•  HASH GROUP BY 指定使用杂凑函数来执行 GROUP BY 操作。
 
•  ORDER GROUP BY 指定使用排序操作来执行 GROUP BY 操作。
 
使用前面的 GROUP BY 范例(请参阅本章的 <检视总计操作> 一节),您可以按照下面使用提示来指定如何执行 HASH GROUP BY 操作:
SELECT CustomerID, SUM(OrderDetails.UnitPrice)
     FROM Orders, OrderDetails
HASH GROUP BY CustomerID
OPTION(HASH GROUP)
________________________________________
说明
GROUP BY 提示彼此独立-每次只能使用其中一种。
________________________________________
 联合提示 下面的提示是用来指定如何执行 UNION 操作:
•   MERGE UNION 使用合并操作来执行 UNION。
 
•   HASH UNION 使用杂凑函数来执行 UNION。
 
•   CONCAT UNION 使用串联功能来执行 UNION。
 
这是一个使用 CONCAT UNION 提示的范例:
SELECT OrderID, CustomerID, EmployeeID, OrderDATE
     FROM orders
     WHERE CustomerID = 'TOMSP'
UNION
SELECT OrderID, CustomerID, EmployeeID, OrderDate
     FROM orders
     WHERE EmployeeID = '4'
OPTION (CONCAT UNION)
________________________________________
说明
UNION 提示也是彼此独立的。
________________________________________
不幸的是,没有任何一定的公式可用以确定哪种 UNION 操作在您的环境中执行的最好。再一次说明,最好的途径就是使用 Query Analyzer 来尝试不同的 UNION 提示,看看哪种可以提供最少的消耗。通常 SQL Server Query Optimizer 可以为 UNION 提示决定最佳策略。
 杂项提示 下面的提示可以用来执行多种的查询操作:
•   FORCE ORDER 强制查询按照查询中数据表出现的次序执行。在预设状态下,SQL Server 可以重新排序数据表存取。
 
•   ROBUST PLAN 强制 Query Optimizer 预备取得最有可能的最大数据列数。
 
以下是使用这个提示的范例:
SELECT OrderID, CustomerID, Employees.EmployeeID, FirstName,
  LastName, OrderDate
FROM Orders, Employees
WHERE Orders.EmployeeID = Employees.EmployeeID
OPTION (ROBUST PLAN)
资料表提示
 
 数据表提示 (table hints)用来控制数据表存取,两种数据表提示如下:
•  FAST n 替代 FASTFIRSTROWS,用来保持向后的兼容性。最佳化查询以获得最前面n列的数据。
 
•  INDEX=index_name 强制 Query Optimizer 在可能时使用指定的索引。在本章中的前面的范例之一示范了如何使用 INDEX 提示:
 
• SELECT OrderID, CustomerID, EmployeeID, OrderDate
•    FROM orders WITH (INDEX = EmployeeID)
•    WHERE EmployeeID = 5
   OPTION (FAST 10)
WITH是选择性的。
这里的 INDEX = EmployeeID 提示将指定使用 EmployeeID 索引。透过指定FAST 10,SQL Server 将最佳化前面 10 列的取得(如果可能的话),然后传回剩下的列。
本章总结
 
在本章中,您学到了如何使用 Query Analyzer 以确定对查询最佳的执行计划和数据存取方法。另外,您还学到了如何使用 Profiler 来检视系统中执行的 T-SQL 陈述式,以及如何执行追踪来确定是否其中一些 T-SQL 陈述式可能导致效能问题。还讨论了如何根据您的数据库和数据以最佳化执行计划和数据库存取方法。最后,您学到了如何使用提示来指定一个特定的执行计划或数据存取方法。在 第 36 章 中,您学习的主题将发展为效能问题以及如何解决效能问题。




34. 使用者与安全性管理
建立与管理使用者登入账户
管理数据库存取权限
管理数据库角色
安全性账户授权
本章总结
本章将学习在 Microsoft SQL Server 2000 环境下管理使用者并确保安全性。安全性管理和备份、回复计划、容量规模及空间管理一样,都是 DBA 例行的工作。少了系统的安全性,数据就会遗失或被破坏。
本章涵盖了使用者和安全性管理有关的主题。我们会学习建立与管理使用者登入账户,以及不同的验证模式;另外还将学习 SQL Server 使用者 ID。 使用者登入账户 (user login)是用来验证使用者是否允许存取该 SQL Server,可透过 Microsoft Windows NT、Microsoft Windows 2000 或 SQL Server 来验证。 使用者ID (user ID)分配使用者权限,用来在个别数据库中存取特定对象。使用者 ID 与使用者登入账户相关,不过两者可以设定一样的名称,也可以设定不一样的名称,这些稍后将在本章讨论。本章学习在 SQL Serve r中分配的不同类型权限,以及如何使用权限。另外也会学习利用角色简化使用者的管理工作。最后会学到的是 SQL Server 2000 安全账户授权。在看完本章后,您应具备管理使用者登入账户和安全性的常识。
建立与管理使用者登入账户
 
现在先透过使用者登入账户,开始管理使用者与安全性的第一步。本节会介绍登入账户的重要性,以及用于维持登入账户的验证模式。接着我们会介绍三种建立登入的方法:使用 SQL Server Enterprise Manager、使用 Transact-SQL(T-SQL),以及使用 建立登入精灵 。最后回学习利用 Enterprise Manager 和T-SQL建立新的使用者账户。
建立使用者登入账户的原因
 
使用者登入账户可达到保护数据的目的,避免数据库被未验证过的使用者有意或无意的更改。利用使用者登入账户可识别 SQL Server 中的每一个授权使用者。每个使用者登入账户都拥有一组唯一的名称和密码。如果没有使用者登入账户,所有对 SQL Server 的连接将使用同一个识别符号,这样就无法根据不同层级的使用者设立不同层级的安全存取范围。
使用者登入账户可设定不同层级的安全存取,也就是用不同的登入账户就有不同存取对象和执行功能的权限。我们可对某些数据库对象加密,例如将预存程序和检视对未验证使用者隐藏定义。使用者登入账户可以允许特定层级的使用者插入或更新新信息至数据库数据表,而一般层级的使用者只能用只读方式存取数据表。
让我们回到 第 18 章 的范例,了解登入账户如何限制数据的存取。范例中利用检视表限制对特定数据的存取。假定一个 Employee 资料表中包含职员姓名、电话号码、办公室号码、等级、工资、奖金等信息,为避免使用者存取数据表中的机密数据,要先建立检视表,只包含如职员姓名、电话号码及办公室号码等较不机密的信息,透过使用者登入账户限制存取基底数据表的数据,仅允许检视表数据的存取。当然,如果没有利用使用者登入账户做控管,而允许任何使用者存取检视表或数据表,就失去了使用检视表的意义。
验证模式
 
验证模式有两种:Microsoft Windows 验证和混合模式验证。在 Windows 验证模式中,操作系统会负责验证使用者,在 SQL Server 中利用操作系统的验证决定使用者的权限。在混合模式验证中,Windows NT/2000 和 SQL Server 同时负责验证使用者。在存取 SQL Server 之前,必须先登入 Windows NT/2000 账户。因此选择验证模式前,必须决定是否要使用双重的验证。让我们更详细的了解这两种验证模式,然后学习执行这些模式。
Windows 验证
 
在 Windows 验证中,SQL Server 透过 Microsoft Windows NT/2000 来提供登入的安全性。当使用者登入 Windows NT/2000,同时确认了使用者账户身份。然后 SQL Server 将验证使用者是否为 Windows NT/2000 确认的使用者,然后依验证身分给与数据库存取的权限。SQL Server 的登入程序结合了 Windows 的安全登入程序,透过 Windows NT/2000 提供的复杂加密过程,建置了网络安全性属性。由于 SQL Server 和 Windows 的登入安全性验证是结合在一起的,所以这种方式不再需要别的验证方法。用来登入的唯一密码就是 Windows NT/2000 的密码。
Windows 验证是比混合验证模式更好的安全性方法,因为它提供了附加的安全性特性,包括安全确认、加密密码、稽核、密码到期时间、最小密码长度,以及在特定次数的失败登入后自动锁定账户。
混合模式验证
 
在混合模式验证中,使用者可以用 Windows 验证或 SQL Server 验证来存取SQL Server。当有一个来自非安全系统的连接时,SQL Server 会验证这个登入,检验是否设定过这个 SQL Server 登入账户。这个账户验证在 SQL Server 中执行,根据储存在数据库中的使用者名称和密码进行检验。在尝试连接 SQL Server 时,系统会提示使用者提供使用者名称和密码。如果没有提供这些信息,SQL Server 系统会拒绝该使用者的存取。
在您执行 Windows 95/98 时无法使用 Windows 验证模式,因此在这些平台上您必须使用 SQL Server 验证(用混合模式验证)。此外,Web 应用程序需要 SQL Server 验证(透过 Internet Information Server,或称为 IIS),因为这些应用程序的使用者并不一定都在同一个网域中,因此就不能依靠 Windows 安全性,这时就需要使用 SQL Server 安全性。其它需要存取数据库的应用程序也同样需要 SQL Server 验证:一些应用程序的开发人员会因为它们的应用程序结构简单而喜欢使用 SQL Server 安全装置。在使用 SQL Server 安全装置时(在信任网络中),应用程序的开发人员不再需要提供应用程序自身的安全性验证,这样可以简化他们的工作。
设定验证模式
 
请依下列步骤,用 Enterprise Manager 设定验证模式:
1. 开启 Enterprise Manager 窗口,在左边窗格中的服务器名称上按一下鼠标右钮,并从快捷菜单中选择 内容 ,进入 SQL Server 属性窗口。按一下 安全性 页签,如图34-1所示。
 
 
图34-1 「SQL Server属性」窗口的「安全性」页签
2. 在这个页签中,选择安全性方法和启动服务账户。在 安全性 区域中,指定是否使用 Windows NT/2000 和 SQL Server(混合模式)验证,或只使用 Windows NT/2000 验证。这里可以指定登入稽核层级。登入稽核层级指定保留哪些登入时的记录。应该根据安全性需要选择稽核等级,有四个等级可使用:
o  无 预设选项;不执行登入稽核。
 
o  成功 记录所有成功的登入尝试。
 
o  失败 记录所有失败的登入尝试。
 
o  全部 记录所有的登入尝试。
 
________________________________________
说明
稽核层级是一个数据库属性,同样的,这个设定将套用到所有的登入上。
________________________________________
3. 在 启动服务账户 区域中,指定在启动 SQL Server 服务时使用的 Windows NT 账户。可使用内建的本机系统账户,或指定一个账户后提供密码。按 确定 接受设定。
登入账户和使用者
 
接下来的几个章节中将学习建立登入账户和使用者。在开始之前,需要先了解何谓登入账户和使用者。这里仅将这两个字词简要的定义。
我们可以看到,要连到数据库中,可能会需要 Windows NT/2000 使用者账户,或许同时也许需要使用 SQL Server 验证。不论使用的是 Windows NT/2000 验证或混合模式验证,连接到 SQL Server 的账户都被称为「登入」账户。除了 SQL Server 登入账户,每个数据库会分配一组指定的使用者,这些使用者是虚拟账户。这些虚拟账户提供 SQL Server 登入账户一个别名。例如在 Northwind 数据库中,也许有使用者的名称为 manager ,而这个使用者名称和 SQL Server 登入账户 guest 有关;在 pubs 数据库中,可能有使用者名称也是 manager ,而这个使用者名称却与 SQL Server 登入账户 sa 有关。在预设情况下,SQL Server 登入账户和数据库使用者 ID 设定没有相关,因此并没有任何权限。
建立 SQL Server 登入账户
 
大部分的管理任务可以使用多种方法执行,而建立使用者登入账户也不例外。您能透过三种途径的任何一种来建立登入:使用 Enterprise Manager、使用 T-SQL 或使用 Create SQL Server Login Wizard。在本节中,您将学到如何使用这三种方法建立 SQL Server 登入账户。
利用 Enterprise Manager 建立 SQL Server 登入账户
 
要利用 Enterprise Manager 建立 SQL Server 登入账户,请按照下列步骤操作:
1. 在 Enterprise Manager 窗口的左边窗格中,展开服务器群组、服务器,然后展开 安全性 数据夹。在 登入 上按一下鼠标右钮,然后在快捷菜单中选择 新增登入 ,进入 SQL Server 登入属性窗口,如图34-2所示。在 一般 页签的 名称 文字方块中键入SQL Server登入账户。如果使用的是Windows验证,那么这个名称必须是有效的Windows NT或Windows 2000账户名称。接下来在 网域 文字方块中指定 Windows NT 或 Windows 2000 的网域。在预设区域指定使用者使用的预设数据库和语言。在 验证 区域中,指定是否使用 Windows NT 或 Windows 2000 账户,或者使用 SQL Server 验证。如果选择 SQL Server 验证,则使用混合模式验证。
 
 
图34-2 「SQL Server 登入属性」窗口的「一般」页签
2. 按一下 服务器角色 页签,如图34-3所示。在这个页签中可以指定新的登入选取的服务器角色,在可使用的角色清单中选择。按一下 属性 允许检视和修改所选取的角色。(有关角色的讨论将在本章的 <管理数据库角色> 一节中进行。)
 
 
图34-3 「SQL Server 登入属性」窗口的「服务器角色」页签
3. 选取 数据库存取 页签,如图34-4所示。这个页签可指定权限使用者可以存取的数据库。(数据库权限将在 <管理数据库存取权限> 一节中说明。)您可选择多个数据库以及对于这些数据库可用的角色。按 属性 就能检视和管理数据库角色属性。
 
 
图34-4 「SQL Server 登入属性」窗口的「数据库存取」页签
4. 完成指定选项之后,按一下 确定 储存登入账户。要看新的登入账户和其它登入账户,可以在 Enterprise Manager 中选取 登入 数据夹。在右边的选单中会列出所有登入账户。
使用 T-SQL 建立登入账户
 
使用 T-SQL 可以建立登入账户,需要使用 sp_addlogin 预存程序或sp_grantlogin 预存程序。sp_addlogin 预存程序只能将 SQL Server 验证过的使用者加入 SQL Server 数据库中。sp_grantlogin 预存程序则可以将 Windows NT/2000 验证过的使用者加入。
sp_addlogin 预存程序的语法如下:
sp_addlogin  [@loginame =] 'login'
        [ , [ @passwd = ] 'password'  ]
        [ , [ @defdb = ] 'database'  ]
        [ , [@deflanguage = ] 'language'  ]
        [ , [ @sid = ]'sid'  ]
        [ , [ @encryptopt = ] 'encryptionoption'  ]
可选择的参数如下:
•   密码 指定 SQL Server 登入账户密码。默认值为 NULL。
 
•   数据库 指定登入账户的预设数据库。默认值为 master 数据库。
 
•   语言 指定登入账户的预设语言。默认值为现有的 SQL Server 语言设定。
 
•   安全性识别码 (sid) 指定安全性识别码(一个唯一的数值)。如果没有指定这个数值,系统将会自动产生一个数值。使用者通常不使用 sid 参数,但是管理员可能在一些情况下会使用到 sid 。当 DBA 执行疑难排解任务时,可能需要使用 sid ,以确定正在检查哪个登入账户。 sid 参数是登入账户的内部识别码。
 
•  encryptopt_option 指定是否在系统数据表中将密码加密。默认值为NULL,表示密码被加密。指定 skip_encryption 表示密码没有加密。如果指定 skip_encryption_old,那么在较早版本的 SQL Server 中已加密的密码将不再被加密。只有在想要避免加密系统数据表中的密码时,才需要更改这个设定。
 
下面是一个简单的新增登入账户的范例:
EXEC sp_addlogin 'PatB'
记住在预存程序名称前要使用 EXEC 关键词。
下面是一个较复杂的新增登入账户范例。
sp_addlogin 'SharonR','mypassword','Northwind','us_english'
这个命令建立了名叫 SharonR 的使用者,使用 mypassword 密码。预设数据库为 Northwind,预设语言为 U.S. English。一般而言,让 SQL Server 来建立安全性识别比您自己来建立要好些。
sp_grantlogin 预存程序有下列语法:
sp_grantlogin 'login_name'
使用 sp_grantlogin 预存程序的范例如下:
EXEC sp_grantlogin 'MOUNTAIN_DEW/DickB'
在增加了这些登入账户之后,在左边的窗格中选取 登入 数据夹,以便在Enterprise Manger 中检视这些登入账户。
使用建立登入精灵
 
可依下列步骤,利用 建立登入精灵 建立 SQL Server 登入账户:
1. 展开一个服务器群组,并选取一个服务器。在 工具 菜单中选择 精灵 。在 选择精灵 对话框中展开 数据库 数据夹,选择 建立登入精灵 ,如图34-5所示,按 确定 。此时将显示 欢迎使用建立登入精灵 ,如图34-6所示。
 
 
图34-5 选择精灵画面

 
 
图34-6 欢迎使用建立登入精灵画面
2. 按 下一步 进入 选取这个登入的验证模式 画面,如图34-7所示。在这个画面中,您可以指定是否使用 Windows 验证或 SQL Server 验证(混合模式)。
 
 
图34-7 选取这个登入的验证模式画面
3. 按 下一步 进入 使用Windows NT的账户验证 画面或 使用SQL Server的验证 画面,出现的画面取决于步骤 2 中选取的验证模式。图34-8显示稍后的画面。在这个画面中指定登入 ID 和密码。如果选择的是 Windows NT 验证,请键入网域名称和使用者账户名称。
 
 
图34-8 使用 SQL Server 的验证画面
4. 按 下一步 ,显示 同意对安全性角色的存取 画面,如图34-9所示。在这个画面中,可以选取分配到该登入账户上的数据库角色。
 
 
图34-9 同意对安全性角色的存取画面
5. 按 下一步 进入 同意对数据库进行存取画面 ,如图34-10所示。在这个画面中可以选取登入账户可以存取的数据库。
 
 
图34-10 同意对数据库进行存取画面
6. 按 下一步 进入 完成建立登入精灵 画面,如图34-11所示,这里可以在文字方块中检查摘要信息。要变更设定可按 上一步 回到之前的画面,按 完成 即可完成建立新登入账户。
 
 
图34-11 完成建立登入精灵画面
建立 SQL Server 使用者
 
SQL Server 使用者可以利用 Enterprise Manager 或 T-SQL 建立。(在 SQL Server 中并没有用来完成这项设定的精灵)。本节中将利用这两种方式建立 SQL Server 使用者。请记住,SQL Server 使用者是为特定的数据库所定义,且特定的使用者登入名称对该数据库有不同的使用权限。SQL Server 使用者 ID 可被视为 SQL Server 登入账户的同义词,但是在登入时两者并不需要使用相同的名称。
________________________________________
说明
建立 SQL Server 使用者前,必须先为该使用者定义 SQL Server 登入账户,因为使用者名称需参照 SQL Server 登入账户。
________________________________________
使用 Enterprise Manager 建立使用者
 
与 SQL Server 登入账户不同的是,登入账户是在 Enterprise Manager 的 Security 数据夹中建立的,而 SQL Server 使用者则在 Enterprise Manager 左侧选单的指定数据库档案夹中建立。要使用 Enterprise Manager 建立使用者,请按照下列步骤操作:
1. 在需要建立使用者的数据库上按一下鼠标右钮,在快捷菜单中选择 新增 ,然后选择 数据库使用者 ,进入 数据库使用者属性 窗口,如图34-12所示。在 登入名称 下拉式清单中键入一个有效的 SQL Server 登入账户名称,并在 使用者名称 文字方块中键入新的使用者名称。在 数据库角色使用权限 清单中选取合适的复选框,为新使用者分配数据库角色。在本章的后面可以看到,为这些角色分配权限,便能够将权限套用到使用者上。
 
 
图34-12 数据库使用者属性画面
2. 按下 属性 按钮进入 数据库角色属性 画面,如图34-13所示。在这个窗口中可以更改选取的数据库角色。这个任务将在本章的 <管理数据库角色> 一节中解释。
 
 
图34-13 数据库角色属性画面
3. 在我们完成了这些设定选项后,按两次 确定 即可建立数据库使用者。
使用 T-SQL 建立使用者
 
要使用 T-SQL 建立数据库使用者,可以执行 sp_adduse 预存程序。这个预存程序可以在 ISQL 或 OSQL 中执行,语法如下:
sp_adduser [ @loginame = ] 'login'
     [ , [ @name_in_db = ] 'user' ]
   [ , [ @grpname = ] 'group' ]
Login 这个参数是 SQL Server 登入账户的名称,是必须提供的数据。user 变量是新的使用者名称,group 则是新使用者所隶属的群组或角色。如果没有指定 user 值,那么它的值会与 login 参数相同。
下面的命令建立了一个新的数据库使用者,其名称为 JackR 和 Windows NT 或Windows 2000 账户 FORT_WORTH/DB_User:
sp_adduser 'FORT_WORTH/DB_User', 'JackR'
FORT_WORTH 是系统或者网域名称,而 DB_User 是 Windows NT 或Windows 2000 账户名称。
管理数据库存取权限
 
 存取权限 (permissions)用来控制数据库对象的存取,并指定可操作特定数据库操作的使用者。可以将服务器和数据库存取权限都设定。服务器存取权限允许 DBA 执行数据库管理任务,数据库存取权限则是用来允许或者禁止存取数据库对象和陈述式。本节中将讨论存取权限的类型,以及如何分配存取权限。
服务器存取权限
 
服务器存取权限是分配给 DBA,允许DBA执行管理任务。这些存取权限定义在固定服务器角色。使用者登入账户也可以分配给固定服务器角色,但是这些角色不能被更改。(在本章稍后的 <使用固定的服务器角色> 一节中将讨论服务器角色。)服务器存取权限包括 SHUTDOWN、CREATE DATABASE、BACKUP DATABASE 和 CHECKPOINT 存取权限。服务器存取权限只能授权 DBA 作为执行管理任务使用,而不需要更改或者授予个人使用者。
数据库对象存取权限
 
数据库对象权限是权限类型中,属于允许数据库对象存取的类型。在存取数据表或检视使用 SQL 陈述式(如 SELECT、INSERT、UPDATE 和 DELETE)存取对象时,就需要使用对象存取权限。使用 EXECUTE 陈述式执行预存程序时也需要对象存取权限。
使用 Enterprise Manager 指定对象存取权限
 
要使用 Enterprise Manager 将数据库对象存取权限授予使用者,请按照下列步骤操作:
1. 展开服务器群组,展开一个服务器,展开需要分配存取权限的数据库,然后选取 使用者 数据夹。在右边窗格中会列出使用者。请在使用者名称上按一下鼠标右钮,并从快捷菜单中选择 内容 ,进入 数据库使用者属性 窗口,如图34-14所示。
 
 
图34-14 「数据库使用者属性」窗口
2. 按下 权限 按钮,进入 数据库使用者属性 窗口,如图34-15所示。(也可以在使用者名称上按一下鼠标右钮,从快捷菜单中选择 所有工作 ,然后选择 管理使用权限 来进入这个个窗口)。这里可以管理分配该使用者的存取权限,可以为该使用者分配多种存取权限,利用画面中的复选框指定 SELECT、INSERT、UPDATE、DELETE、EXEC 和 Declarative Referential Integrity(DRI)窗体数据列的存取权限。这些对象列在 对象 数据列中。也可以使用画面上方的选项来列出所有的对象,或只显示这个使用者有权限的对象。
 
 
图34-15 数据库使用者属性窗口中的权限窗口
使用 T-SQL 分配对象存取权限
 
执行 GRANT 陈述式,可利用 T-SQL 将对象存取权限指定给使用者。GRANT陈述式的语法如下:
GRANT  {ALL |  permission}
       [ column ON  {table | view} ] |
       [ ON table(column) ] |
       [ ON view(column) ] |
       [ ON  {stored_procedure | extended_procedure} ]
TO security_account
       [ WITH GRANT OPTION ]
       [ AS  {group | role} ]
security_account 参数必须是下列账户类型之一:
•  Microsoft SQL Server使用者
 
•  Microsoft SQL Server角色
 
•  Microsoft Windows NT 或 Windows 2000 使用者
 
•  Windows NT 或 Windows 2000 群组
 
使用 GRANT OPTION 关键词允许使用者将该权限授予其它使用者。这在授予存取权限给其它的 DBA 时很有用。然而,应该要小心使用 GRANT 选项。
AS 选项指定要执行 GRANT 陈述式的权限。GRANT 陈述式必须在使用者或角色有被授予权限时才能执行。
GRANT 陈述式可以按照下面的方式使用:
GRANT SELECT , INSERT, UPDATE
ON Customers
TO Guest
WITH GRANT OPTION
AS Accounting
因为 Accounting 角色可以在 Customers 资料表上授予存取权限,所以要使用AS Accounting 选项。GRANT OPTION 关键词让 MaryW 可将存取权限授予其它的使用者。
________________________________________
相关信息
要检视 GRANT 陈述式中指定的存取权限清单,请参阅< 在线丛书 >索引中的GRANT。
________________________________________
使用 T-SQL 撤销对象存取权限
 
您可以用 T-SQL REVOKE 命令来撤销使用者的对象存取权限。REVOKE 陈述式的语法如下:
REVOKE [ GRANT OPTION FOR ]
      { ALL [ PRIVILEGES ] | permission }
            [ column  ON  {table | view} ] |
            [ ON table(column) ] |
            [ ON view(column) ] |
            [ ON   {stored_procedure | extended_procedure} ]
{ TO | FROM }  security_account
            [ CASCADE ]
            [ AS  {group | role}  ]
security_account 参数必须是下列账户类型之一:
•  Microsoft SQL Server 使用者
 
•  Microsoft SQL Server 角色
 
•  Microsoft Windows NT 或 Windows 2000 使用者
 
•  Windows NT 或 Windows 2000 群组
 
与撤销存取权限相同,GRANT OPTION FOR 选项允许您撤销之前用 GRANT OPTION 关键词授予的存取权限。AS 选项指定要执行 REVOKE 陈述式的权限。
以下是使用 REVOKE 陈述式的范例:
REVOKE ALL
ON     Customers
TO     MaryW
REVOKE AL L陈述式将移除在 Customers 数据表中使用者 MaryW 拥有的所有存取权限。
________________________________________
相关信息
要检视在 REVOKE 陈述式中指定的存取权限清单,请查阅《在线丛书》索引中的 REVOKE。
________________________________________
数据库陈述式存取权限
 
除了数据库对象存取权限,您还可以分配陈述式存取权限。对象存取权限让使用者存取数据库中现存的对象,而陈述式存取权限则授权使用者建立数据库对象,包括数据库和数据表。陈述式存取权限如下:
•   BACKUP DATABASE 执行 BACKUP DATABASE 命令
 
•   BACKUP LOG 执行 BACKUP LOG 命令
 
•   CREATE DATABASE 用来建立新的数据库
 
•   CREATE DEFAULT 用来建立可关联至字段的默认值
 
•   CREATE PROCEDURE 用来建立预存程序
 
•   CREATE RULE 用来建立规则
 
•   CREATE TABLE 用来建立新的数据表
 
•   CREATE VIEW 用来建立新的检视
 
陈述式存取权限可以用 Enterprise Manager 或 T-SQL 分配。
使用 Enterprise Manager 分配陈述式存取权限
 
要使用 Enterprise Manager 为使用者授予数据库的陈述式存取权限,请按照下列步骤操作:
1. 展开一个服务器群组,展开一个服务器,然后展开 数据库 数据夹。在需要分配存取权限的数据库上按一下鼠标右钮,并从快捷菜单中选择 内容 ,显示数据库的属性窗口,如图34-16所示。
 
 
图34-16 数据库的属性窗口
2. 选取 权限 页签,如图34-17所示。在这里可以为存取该数据库的使用者分配存取权限。这些数据列包含复选框,规定了所要分配的陈述式存取权限,而 使用者/角色 字段列出了存取这个数据库的使用者和角色。
 
 
图34-17 数据库属性窗口的权限页签
使用 T-SQL 分配陈述式存取权限
 
您可以使用 GRANT T-SQL 陈述式为使用者分配陈述式存取权限。GRANT 陈述式的语法如下:
GRANT { ALL | statement }
TO    security_account
可以分配给使用者的陈述式存取权限包括 CREATE DATABASE、CREATE DEFAULT、CREATE PROCEDURE、CTEATE RULE、CREATE TABLE、CREATE VIEW、BACKUP DATABASE 和 BACKUP LOG,如前所述。例如要为使用者账户 Elea 新增 CREATE DATABASE和CREATE TABLE 陈述式存取权限,请使用下面的命令:
GRANT CREATE DATABASE,CREATE TABLE
TO    'Elea'
所以,为使用者账户新增陈述式存取权限其实并不困难。
使用 T-SQL 撤销陈述式存取权限
 
您也可以使用 T-SQL 陈述式 REVOKE 来撤销使用者账户的陈述式存取权限。REVOKE 陈述式的语法如下:
REVOKE { ALL | statement }
FROM   security_account
例如,要从使用者账户 Elea 上撤销 CREATE DATABASE 陈述式存取权限,可使用下列命令:
REVOKE CREATE DATABASE
FROM   'Elea'
正如所见,撤销使用者的陈述式存取权限也不是个复杂的过程。
管理数据库角色
 
使用数据库角色可以简化管理使用者存取权限的工作。数据库角色就是设计用来允许一组使用者接受同样的数据库存取权限,这样便不需要个别的分配这些存取权限。不要分配给每个使用者个人的存取权限,可以为一组使用者建立角色,然后分配存取权限。
角色是为了特殊的工作群组、工作类别或工作任务而设计。在这种情况下,根据新使用者所执行的工作,它们可以成为一个或多个数据库角色的成员。例如,角色可能定义成工作类别,如支付性账户、接受性账户、工程以及人力资源等。当一个使用者加入这些部门或群组中时,他或她就被分配为这个角色的一个成员。一个使用者可以是一个或多个角色的成员,但是并不一定要求使用者成为某一角色的成员。除了成为数据库角色的成员以外,使用者也可以分配个人存取权限。
建立和修改角色
 
和 DBA 所执行的大多数任务一样,建立和修改数据库角色也可以透过Enterprise Manager 或 T-SQL 命令来完成。(SQL Server 没有提供这一类的精灵。)这两种方法必须完成同样的例行性任务:
•  建立数据库角色。
 
•  为角色分配存取权限。
 
•  为角色分配使用者。
 
当检视角色时,可以看到分配给角色的存取权限和分配给角色的使用者。
使用 Enterprise Manager 管理角色
 
要使用 Enterprise Manager 建立数据库角色,请按照下列步骤操作:
1. 展开一个服务器群组,展开一个服务器,然后展开 数据库 数据夹。在需要建立角色的数据库上按一下鼠标右钮(本范例使用 Northwind),并从快捷菜单中选择 新增 ,接着选择 数据库角色 。另外一种方法,可以展开数据库,在 角色 上按一下鼠标右钮,并从快捷菜单中选择 新增数据库角色 。这两种方法都可进入 数据库角色属性 窗口,如图34-18所示。
 
 
图34-18 「数据库角色属性」窗口
2. 在 名称 文字方块中键入名称来为角色分配描述性名称-请选择一个有助于记住角色功能的名称。
3. 按一下 新增 为角色分配使用者。这时将会显示可以存取该数据库的使用者账户清单,如图34-19所示。选取要分配给该角色的使用者。如果要取消选择使用者,只要在使用者名称上再按一下就可以了。在完成修改角色成员后,按一下 确定 即可建立了新角色。现在返回 Enterprise Manager 窗口中。
 
 
图34-19 新增角色成员对话框
4. 要为角色分配存取权限,先展开 角色 数据夹开启 数据库角色属性 窗口,在角色名称上按一下鼠标右钮,并从快捷菜单中选择 内容 。然后按一下 权限 ,进入 数据库角色属性 - Northwind 窗口,如图34-20所示。
在这个窗口中,可以为数据库中的对象角色分配不同的存取权限。选择清单中适合的复选框。数据库对象是列在 对象 数据列中的。选择窗口上方的选项可以检视所有的对象,或是列出这个角色有权限的对象。一旦分配了一个角色给某个使用者,使用者就获得了分配给这个角色的所有存取权限。
在建立了角色后,可以在 数据库角色属性 窗口中修改。要修改角色,请按照为角色增加存取权限的步骤操作。也可以在 数据库角色属性 窗口中新增以及删除使用者和存取权限。
使用 T-SQL 管理角色
 
也可以使用 sp_addrole 预存程序来建立角色。sp_addrole 预存程序的语法如下:
sp_addrole [ @rolename = ] 'role'
       [ , [ @ownername = ]  'owner' ]

 
 
图34-20 数据库角色属性 - Northwind窗口
例如,要在 Northwind 数据库中加入一个名称为 readonly 的角色,请使用下列 T-SQL 命令:
USE Northwind
GO
sp_addrole 'readonly' , 'dbo'
GO
USE Northwind 命令选取 Northwind 为目前数据库。如果没有指定数据库,那么在预设数据库中会建立角色。
这个预存程序只能建立角色。要为角色增加存取权限,请使用前面描述的 GRANT 陈述式。要为角色删除存取权限,请使用 REVOKE 陈述式。
例如,要为 readonly 角色增加 Employees、Customers 和 Orders 数据表的SELECT 存取权限,请使用下列的 GRANT 陈述式:
USE Northwind
GO
GRANT SELECT
ON    Employees
TO    readonly
GO
GRANT SELECT
ON    Customers
TO    readonly
GO
GRANT SELECT
ON    Orders
TO    readonly
GO
要为角色增加使用者,请使用 sp_addrolemember 预存程序。sp_addrolemember 预存程序的语法如下:
sp_addrolemember 'role','security_account'
下列命令可为 readonly 角色增加使用者:
USE Northwind
GO
sp_addrolemember 'readonly' , 'Guest'
GO
使用固定的服务器角色
 
在 SQL Server 安装时,建立了大量预先定义的服务器角色。这些固定服务器角色被用来授予存取权限给 DBA,这些角色包含了服务器存取权限以及对象和陈述式存取权限,清单如下:
•  bulkadmin 可以执行大量插入
 
•  dbcreator 可以建立和变更数据库
 
•  diskadmin 可以管理磁盘档案
 
•  processadmin 可以管理S QL Server 程序
 
•  securityadmin 可以管理登入账户和建立数据库存取权限
 
•  serveradmin 可以设定任何服务器选项,并且可以关闭数据库
 
•  setupadmin 可以管理连结的服务器和启动程序
 
•  sysadmin 可以执行任何服务器行为
 
为使用者账户分配固定服务器角色,可让使用者执行角色所拥有存取权限的管理任务。依需要让所有的DBA使用相同的管理账户可能会更好些。与数据库角色相比,固定服务器角色比个人存取权限更容易维护,但是固定服务器角色是不能修改的。您可以按照下列步骤为一个使用者分配固定服务器角色。
1. 在 Enterprise Manager 中展开一个服务器群组,展开一个服务器,展开 安全性 数据夹,然后选取 服务器角色 。在需要加入使用者的固定服务器角色上按鼠标右钮,并从快捷菜单中选择 内容 ,进入 服务器角色 窗口,如图34-21所示。
 
 
图34-21 服务器角色窗口
2. 按 新增 ,为新增的使用者账户分配固定服务器角色。这将呼叫 新增成员 对话框,如图34-22所示。
 
 
图34-22 新增成员对话框
3. 选取了需要加入固定服务器角色的使用者之后,按一下 确定 ,返回 服务器角色属性 窗口。请按一下 确定 为安全性角色新增使用者。
安全性账户授权
 
SQL Server 2000 使用 Kerberos 安全模式建立安全性。(关于 Kerberos 安全模式的信息可参阅 第 2 章 。)SQL Server 2000 使用 Kerberos 通讯协议来支持客户端与服务器之间的相互认证。这使得客户端的安全识别能够在计算机之间流通,于是就可连接到不同的服务器上;登入新的服务器时,可使用个人化的用户识别进行数据的存取。这就是安全性账户授权。
我们来看一个安全性账户授权的例子。假定一个用户连接到 Server A 为NTDOMAIN/AlexR,而 ServerA 又与 ServerB 相连接。那么 ServerB 就知道连接的安全性识别为 NTDOMAIN/AlexR。这减少了用户登入到 ServerB 的需求。
如果要使用安全性账户授权,所连接的所有服务器都必须能够执行 Windows 2000,并支持 Kerberos,而且您必须正在使用 Active Directory 服务。下列选项必须在 Active Directory 中设定,以便进行授权:
•   账户敏感无法授权 要求授权的使用者绝对不能选择这个选项。
 
•   账户可以授权 SQL Server 2000 的服务器账户一定要选这个选项。
 
•   计算机可以授权 执行 SQL Server 2000 的服务器一定要选这个选项。
 
设定 SQL Server
 
在使用安全性账户授权之前,必须先设定 SQL Server 2000 来接受授权。授权促成彼此相互确认。要使用安全性账户授权,SQL Server 2000 必须有 Windows 2000 账户网域管理员分配的 Service Principal Name(SPN)。SPN 必须分配到计算机上 SQL server 的服务器账户。SPN 必须证明 SQL server 是经由特定服务器以及 Windows 2000 账户网域管理员认证的。您可以让您的网域管理员使用在 Windows 2000 Resource Kit 上取得的 Setspn 公共程序,来为 SQL Server 建立一个 SPN。
要建立 SPN,请执行下列命令:
setspn -A MSSQLSvc/Host:port serviceaccount
以下为使用这个命令的范例:
setspn -A MSSQLSvc/MyServer.MyDomain.MyCompany.com sqlaccount
________________________________________
相关信息
关于 Setspn 公用程序的相关信息,请参阅 Windows 2000 文件。
________________________________________
您也必须用 TCP/IP 来使用安全性账户授权,不能使用已命名的管道,因为 SPN要使用特定的 TCP/IP 通讯端。如果使用多重连接埠,每个连接埠都必须有 SPN。
您可以用 LocalSystem 账户授权。SQL Server 将在服务器启动时自己注册登记,并且自动登记 SPN。这个选项比使用网域的使用者账户来授权还要容易。然而,当 SQL Server 关闭时,SPN 将无法替 LocalSystem 账户注册。为了在 LocalSystem 账户之下授权,请在 Setspn 公用程序中执行下列命令:
setspn -A MSSQLSvc/Host:port serviceaccount
________________________________________
说明
如果您要在 SQL Server 2000 中变更服务器账户,您必须删除之前定义的SPN,然后建立新的账户。
________________________________________
本章总结
 
本章学习了 SQL Server 使用者和安全性管理,也看到了如何使用数据库登入账户和数据库使用者账户允许数据库的存取。此外还学习如何建立与管理登入账户和数据库使用者,并学到了如何利用数据库角色简化使用者管理,并依照工作性质分配角色的存取权限。角色可以分配给多个使用者,让分配存取权限和修改变得更加容易。此外也看到了被称为固定服务器角色的特殊角色,这些角色是用来为使用者和 DBA 分配管理存取权限。最后我们看到了在 SQL Server 2000 中安全性的提升,使得服务器之间的安全性账户更能够安全地流通。在 第 35 章 中,我们将学习 SQL 预存程序以及如何调校 SQL 查询。




33. 还原及回复数据库
还原方法
执行数据库还原
规划严重损坏的回复
本章总结
在 第 32 章 中,我们学到了系统备份的重要性,以及如何执行备份。本章将继续上一章所提的数据库保护与建立的说明。我们将学习如何还原数据库、如何回复系统,还有数据库回复的运作方式。正如您所见,备份执行的类型会影响到回复的进行。除了学习关于还原与回复数据库,也会介绍 记录文件传送 (log shipping)。记录文件传送是 Microsoft SQL Server 2000 中的新功能,让您用原始的服务器交易纪录在另一个服务器上建立备用副本。
________________________________________
说明
有些 DBA 提到还原与回复数据库的过程都称作 recovering the database。然而,这些程序是大不相同的。 第 32 章 说明了从备份还原数据库与 SQL Server 回复过程的差异。在任何情况下,将数据库带回系统失败前的状态,就是备份、还原和回复操作执行的主要目标。
________________________________________
还原方法
 
如前所提,执行备份的类型影响了还原操作的性质。在这个章节中我们将学习如何从完整备份、差异式备份、以及交易纪录备份执行还原。
从完整备份还原
 
从完整备份还原是相当简单直接的过程:只要用 SQL Server Enterprise Manager或 Transact-SQL (TSQL)命令还原备份文件。本章稍后会有这两种方法的使用说明。如果在完整备份后,打算从差异式备份还原,只要确定有最近的交易纪录备份,如本章后面 < 从交易纪录备份还原 > 章节所言,并在执行还原时指定 NORECOVERY 选项就行了。
________________________________________
说明
还原操作有个重要的特性,就是 RECOVERY 的选项。它命令 SQL Server 在还原完成后用联机交易纪录来回复数据库。如果想利用差异式备份文件或者交易纪录文件,记得要确定已经指定 NORECOVERY 选项。
________________________________________
从差异式备份还原
 
要从差异式备份还原,必须先从完整备份还原,然后还原上次完整备份后的所有差异式备份文件。记住,差异式备份是用来备份在最近一次完整备份或差异式备份后更改过的信息。确定您使用的是 NORECOVERY 选项,除非您正在还原最后一个备份文件,而还原最后一个备份文件可以用 RECOVERY 选项。如果在差异式备份之外还从交易记录文件执行还原,就必须同时备份目前的记录文件并应用所有更改过的记录文件,这将在下一节中提到。
从交易记录文件备份还原
 
执行回复操作将使数据库的状态返回到失效前的那一点,先还原数据文件,然后还原从开始备份以来对数据库的更改内容。您可以储存所有失效以来的交易记录文件备份来还原这些变更。
为了确保在还原这些记录文件的过程中没有遗失任何最新交易,必须先保存目前的记录文件。如果忘了保存目前的记录文件,会因为还原操作覆写交易记录而遗失记录在记录文件中的大部分最新的更改。
要使用交易记录文件将数据库还原到失效前的状态,请依下列步骤进行(这些是建立在 第 32 章 中所学到的技术基础上):
1. 使用 NO_TRUNCATE 选项备份目前使用中的交易记录文件。
2. 还原最近的完整备份。
3. 还原所有的差异式备份,将数据库还原到最后的备份状态。
4. 还原所有从最后的差异式备份以来的交易记录文件备份,以重置所有自最后备份以来所发生的交易。
5. 还原在步骤 1 中建立的交易记录文件备份,让数据库回到失效前的状态。
在 BULK_LOGGED 回复模式中还原数据库
 
如果正在 BULK_LOGGED 回复模式中执行数据库,需要还原时就必须再做一次记录操作。这些操作包括 SELECT...INTO、BULK COPY、BCP 和一些 CREATE INDEX 操作,还有已在上一章谈过的文字操作。如果觉得这里所谈的内容过于麻烦,可以不要在 BULK_LOGGED 回复模式中执行数据库。
执行数据库还原
 
使用 Enterprise Manager 或 T-SQL 命令可执行还原操作--这两种方式得到的结果相同。与备份操作不同,SQL Server 没有提供还原操作精灵。
使用 Enterprise Manager 执行还原
 
要使用 Enterprise Manage r执行还原操作,请按照下列步骤操作:
1. 在 Enterprise Manager 中,在要还原的数据库名称上按鼠标右钮,在快捷菜单上选取 所有工作 ,然后选择 还原数据库 ,进入 还原数据库 对话框,如图33-1所示。
 
 
图33-1 「还原数据库」对话框中的「一般」页签
2. 在 一般 页签的顶端是 还原成数据库 下拉式清单,这个清单可指定这个备份将被还原的数据库型态。图33-1显示选择了 Example 数据库。
这里并不要求直接用同样的名称来还原数据库-实际上,应该要使用另一个数据库名称。例如,假定某个使用者意外地删除了一个数据表,想要还原完整的数据库,那么就会将所有人的数据还原成较早的数据。但是,其实可以将数据还原到重新命名的数据库中,取出被删除的数据表,然后将这个数据表插入到仍在工作的数据库中。
3. 接着指定还原操作的类型: 数据库 、 档案群组或档案 或者 来源装置 。 数据库 选项可指定还原数据库。 档案群组或档案 选项可指定还原的档案群组或档案。 来源装置 选项可指定还原的装置,装置的内容将决定还原的类型。图33-1显示选择了数据库选项。
4.  参数 区域可以让您设定是否要显示其它数据库的备份(从另一个数据库的备份进行还原),应该要先还原哪个备份(如果设定了多个可用的备份),还有是否应该执行 还原时间点 。 还原时间点 能够还原数据到特定时间的状态。例如,如果在12:01时意外的删除了数据表,可以用 还原时间点 还原12:00时的数据库,刚好在删除发生之前。因为有全部可用的备份清单,可以选择需要使用的备份。如果没有强制还原最新的备份,那么数据库的所有备份都可供选择。
在 还原数据库 对话框中可选择一组备份,然后选择 属性 按钮检视内容。 备份集属性 窗口如图33-2所示。

 
 
图33-2 备份集属性窗口
5. 选择 确定 ,返回 还原数据库 对话框的 一般 页签,并选择 档案群组或档案 显示一个不同的画面,如图33-3所示。图33-3显示 Example 数据库中所有的档案和档案群组备份。要检视这些档案和档案群组备份的属性,请选取档案或档案群组然后选择 属性 。
 
 
图33-3 选取档案群组或档案选项后,还原数据库对话框的一般页签
6. 现在选择 来源装置 ,如图33-4所示。当选取一个还原的特殊备份装置时,会需要用到这个选项。必须以手动选取这组备份,然后指定 SQL Server 是否应该执行完全还原、差异还原、交易记录还原或档案和档案群组还原。也可以让 SQL Server 读取备份信息,并将这些信息与其它备份历史信息一起储存在 msdb 数据库。如果要执行数据库还原,这些关于备份的信息就可派上用场了。
7. 选取 还原数据库 对话框的 选项 页签,如图33-5所示。在这个页签顶端会看到3个复选框。 备份还原后,逐一退出已插入的磁带 复选框可确保磁带不会留在磁带机中被覆写。选择 还原备份前,先提示我 选项提供改变执行备份的机会。而选择 强制对现有的数据库进行还原 复选框让您用还原的数据库覆写现存的数据库。在这个页签,可以在一个新的数据文件名之下还原数据库,这对于保留原始数据库是很有用的。
 
 
图33-4 选取来源装置选项之后,还原数据库对话框的一般页签

 
 
图33-5 还原数据库对话框的选项页签
页签中其它的选项可指定在回复完成后数据库应该保持的状态,如下:
o  保持数据库运作,不还原额外的新增交易记录 这个选项不允许有进一步的差异还原或交易记录还原的回复。实质上是在还原中设定了 RECOVERY 标记。如果选了这个选项,就不能还原交易记录文件备份。
 
o  使数据库不运作,但还可以还原额外新增的交易记录 这个选项在还原中设定了 NORECOVERY 标记。设定了这个标记,就能应用进一步的差异式备份还原和交易记录文件备份还原。在还原进行过程中,数据库处于无法操作状态,这表示在完成整个还原之前,使用者无法存取这个数据库。
 
o  保持数据库为只读的状态,并可以还原额外新增的交易记录 这个选项也在还原中设定 NORECOVERY 标记,可以执行差异式备份还原和交易记录还原。和前面一个选项不同的是在执行还原操作时,使用者可以只读的存取这个数据库。
 
8. 在完成设定选项后,选择 确定 来开启还原操作。透过一个消息框可以了解还原操作的过程,如图33-6所示。当还原操作完成时,会看到一个状态方块,通知还原成功或失败。
 
 
图33-6 「还原进度」消息框
________________________________________
说明
SQL Server 备份装置支持多个不同备份操作的输出。反之亦然:单一备份可以分散到多个装置当中。多个备份装置群组的内容形成一个备份称为备份集(backup set)。因此一个备份装置(磁带、磁盘档案等)可以支持多个不同数据库备份集或多个同一数据库的备份集。
________________________________________
使用 T-SQL 执行还原
 
RESTORE T-SQL 命令和 BACKUP 命令类似( 第 32 章 中曾经讨论过)。如同BACKUP 命令,第一次使用时可能相当困难,但是一些 DBA 还是喜欢将他们的管理程序放置到 SQL 命令文件中,以便于重复执行这些功能。和 BACKUP 命令一样,RESTORE 命令提供了比 Enterprise Manager 更多的附加选项。
在本节中,我们将讨论 RESTORE 命令的语法以及这个命令提供的多种选项。RESTORE 命令有两种形式显示如下:
•   RESTORE DATABASE 还原完整的数据库、档案或档案群组。
 
•   RESTORE LOG 还原交易记录文件。
 
如您所见,所用的命令要依照执行还原操作的类型而定。因为这些命令共享大部分的选项,所以我们稍候将在一个清单中讨论这两种还原类型(数据库和记录文件)的所有选项。
RESTORE 陈述式
 
执行完整数据库还原时 RESTORE 陈述式的语法如下:
RESTORE DATABASE database_name
[   FROM backup_device  ]
[   WITH options  ]
这个陈述式只要求数据库的文件名称和备份所在的位置。
执行档案和档案群组还原时陈述式的语法如下:
RESTORE DATABASE database_name
[  FILE = file_name  ]
[  FILEGROUP = filegroup_name  ]
[   FROM backup_device  ]
[   WITH options  ]
这个陈述式只要求数据库名称、文件名称或档案群组名称和备份所在的位置。
执行交易记录还原时陈述式的语法如下:
RESTORE LOG database_name
[   FROM backup_device  ]
[   WITH options  ]
就如同其它的命令,database_name 是还原将要执行的数据库名称。backup_device 参数可以是逻辑备份装置名称或实体装置的名称。如果要指定一个实体装置,必须限定它的装置类型-也就是说,装置名称前面必须加上 DISK=、TAPE= 或 PIPE=。可以指定一个或多个装置,中间以逗号隔开。
________________________________________
说明
如果没有提供 FORM 子句,还原将无法进行,而且仍然会执行回复(除非执行NORECOVERY 选项)。这项技术可以用来将数据库设定为回复模式,而不还原其它附加数据。例如,可以执行多个差异还原操作,然后执行 RESTORE 陈述式,不需要 FORM 子句来将数据库设定为回复模式,就能够启动回复过程。
________________________________________
选项
 
表33-1列出了 RESTORE 命令可用的选项。如您所见,在执行还原操作时,这些选项提供了很大的弹性空间(如果列出的选项只对交易记录还原有用,将会标示其限制性)。
表33-1 RESTORE 命令选项
选项  说明
RESTRICTED_USER 设定新还原数据库的安全性,只有 db_owner、dbcreater 和 sysadmin 角色成员才能存取该数据库。
FILE = file_number 如果在储存媒体中有多个备份集,可用来识别所使用的备份集。例如设定该数值为2,则使用磁带上的第二个备份集。
PASSWORD = password 指定储存备份的密码。
MEDIANAME =media_name 指定媒体的名称。
MEDIAPASSWORD = password 指定储存媒体的密码。
MOVE 'logical_file_name'
TO 'OS_file_name' 更改还原档案的位置,例如:MOVE 'Northwind' TO 'D:/data/Northwind.mdf'。如果旧的磁盘无法使用,而需要还原到新的磁盘上时,可以使用这个选项。
NORECOVERY |RECOVERY |
STANDBY = undo_file NORECOVERY 指定在还原后,交易将无法退回或重新进行。如果将还原其它的备份(差异式备份或交易记录文件备份),则需要用到这个选项。REVOVERY 为预设选项,它指定执行回复操作,并退回每个没有提交的变更。STANDBY 指定在还原需要还原情况下,建立还原(undo)档案。
KEEP_REPLICATION 指定当数据库还原时复制设定要保存下来。
NOUNLOAD | UNLOAD NOUNLOAD 指定在还原完成后不卸载储存媒体(例如,覆写备份磁带并弹出)。UNLOAD 为预设选项,指定在还原完成后卸载储存媒体。
REPLACE 指出即使数据文件已经存在,SQL Server 仍将还原这些档案。现存的档案将被删除和覆写。如果没有指定 REPLACE,那么 SQL Server 将会核对 database_name 是否已经存在。如果已经存在,那么将终止还原操作。这个安全特性帮助避免无意地将还原覆写正在工作的数据库。
RESTART 指定 SQL Server 在还原操作被中断后重新启动还原操作。
STATS [ = percentage ] 在还原操作完成了指定的百分率后显示讯息。如果需要监控操作的过程,这个选项将会很有用。
PARTIAL 指定执行部份还原。
STOPAT = date_time
(log restore only) 指定数据库回复到 data_time 指定时刻的数据状态(只对记录文件还原有效)。
STOPATMARK = 'mark' 指定还原操作进行到标记处。
STOPBEFOREMARK = 'mark' 指定还原操作进行到标记之前。
________________________________________
说明
命名交易(Named transactions)是 SQL Server 2000 中的新功能。它们是使用命令 BEGIN TRANSACTION ... WITH MARK 的 mark_name 选项建立的,特点是可以使用 RESTORE 命令中的 STOPATMARK 和 STOPBEFOREMARK 功能。
________________________________________
________________________________________
真实世界 使用RESTORE
这里有几个使用 RESTORE T-SQL 命令的例子。
这个陈述式还原 Example 数据库的数据文件:
RESTORE DATABASE Example
FROM Backup_Dev_1, Backup_Dev_2
WITH
NORECOVERY,
STATS = 5
GO
这个陈述式还原 Example 数据库的交易记录文件:
RESTORE LOG Example
FROM Backup_Dev_3, Backup_Dev_4
WITH
NORECOVERY,
STATS = 5,
UNLOAD
GO
和还原的结果一样,输出将显示操作完成的百分率。将通知还原了多少页面、还原花了多少时间,以及还原执行的速度(MB/sec)。
现在可用以下的命令回复数据库:
RESTORE LOG Example
WITH RECOVERY
GO
您将再次看到关于还原操作的统计。
________________________________________
规划严重损坏的回复
 
只有简单地丛集化服务器( 第 12 章 所讨论的)或使用 RAID( 第 5 章 所讨论的)来改善系统正常的工作时间是不够的。您必须在严重损坏发生前做好回复的计划。熟悉如何在必要时执行有效的数据库的备份和还原是十分重要的,但是还是必须准备好在必要时从一无所有开始重建系统。准备工作包括档案管理和计划编制。此外还要使用新的 SQL Server 2000 中还原的功能来提供足够的回复能力。这个功能让交易记录文件可以从主要系统移至备份系统中运作。
作为一个 DBA,应该规划一个最大工作时间的计划。这个计划应该包括下列组件:
•  记录当前组态档案
 
•  建立容错环境
 
•  准备实时回复
 
•  记录数据库回复计划档案
 
大部分的步骤都涉及到计划编制和档案管理。通常回复计划并没有记录,并且只有计划的开发者才能执行这个计划,一旦这个特定成员未能出现,就会出现严重损坏。
________________________________________
说明
确认记录的严重损坏回复计划档案,并指派候补人员在严重损坏发生时,您无法在场时的执行计划。
________________________________________
记录当前组态档案
 
如果建立当前组态的步骤没有很好的记录成档案,那么可能在系统需要重新建构或者在系统中增加新的硬件时会出现问题。记录当前组态档案能够更快速的重建、重新安装和重新设定系统。确定已经包括了下列信息:
•   硬件配置 包括硬件的类型和数量、RAID组态和其它选项。
 
•   安装的软件产品 包括安装在服务器上所有软件的完整信息。
 
建立容错环境
 
就像 第 5 章 看到的,容错 RAID 磁盘区的使用可以大大的降低系统失效的可能性。磁盘是机械组件,跟对象一样会有磨损。使用容错磁盘区,就能在重新安装操作系统、SQL Server 和重建来自备份的数据库时减少许多麻烦,重建过程是一个耗时又耗力的过程(耗费主要在劳动和系统故障期间损失的收入方面)。
如果容错磁盘损毁了,请尽可能快的将它更换。总会有磁盘可能损毁,而一些容错的形式可以在只损毁一个磁盘的情况下继续工作。可准备磁盘随时备用。
准备实时回复
 
准备好在必要时回复数据库。备份应该储藏在其它地方,防止如火灾或洪水的灾难,但您还是应该在手边保存有最近的备份,因为您可能无法很快速的从其它地方取到备份。备份阶段区域(backup staging area)是一种最受欢迎的方式,用这种方式可以在工作站保存最新的备份,还可以提高备份和还原的效能。备份阶段区域在网络上某处磁盘中储存最新的数据库和交易记录文件备份。在需要还原时,不需要使用磁带或从远离工作站的储藏处取得备份─还原可以立即进行。如果需要立即执行还原,这种技术就很有用了,但是由于必须占用硬件资源来储存备份,因此它的硬件需求很高。必须考虑预算和需求来决定是否需要。
记录数据库回复计划档案
 
因为在数据库必须回复的情况发生时,您也许不在现场,所以应该谨慎记录数据库回复计划,并和其它成员共享这些信息,这样在必要时他们就可以回复系统。如果自最后一次数据库还原之后过了很长的时间,数据库回复计划档案也会是一个有效的备忘手册。在任何事件中,保有数据库回复计划的手写拷贝都能使还原过程执行的更加平稳。
记录文件传送
 
SQL Server 2000 中的记录文件传送功能让您将最新交易记录文件应用在备用系统中,以建立备用系统并随时更新。备用系统保持参数回复模式,持续地让交易记录文件应用其上。即使系统在回复模式仍可以进行只读查询,因此可以让您使用备用系统来卸除报告任务。
在主要服务器的失效事件中,备用服务器可以简单而快速地到新的服务器上。这个功能已经有很多人在 SQL Server 7 中使用过,在 Microsoft 中也可支持,还加进一些好用的功能。这些功能包括透过 数据库维护计划精灵 和 SQL Server 代理程序启动与维护备用系统的能力。
本章总结
 
关于数据库备份、还原和回复操作的讨论到此结束。在这两章中,您已经学到了如何有效的进行系统的备份和还原,以及 SQL Server 回复是如何运作的,您也看到了如何使用 Enterprise Manager 和 T-SQL 命令执行这些操作。本章着重在讨论回复操作和准备严重损坏回复计划。记住,系统的安全性是 DBA 的主要职责之一。




32. 备份SQL Server
备份的术语
系统故障
SQL Server记录文件
备份方法
执行备份
排程备份
改善备份
本章总结
将数据库备份是 DBA 最重要的任务之一。备份和仔细的还原计划可在系统失效时将数据还原。DBA 的责任是保持系统的执行状态,并在失效时尽快还原所有的服务。系统停止运作会造成许多不便,有时更要付出昂贵的代价,因此在系统停止运作时得很快的取得取得数据库备份。有些技术会对系统失效的还原有帮助,如丛集和容错磁盘子系统,但是还是比不上一个好的计划和可靠的备份。
因为备份、还原和复原数据库的主题十分重要,因此我们会分成两章的来讨论。本章中将学习 SQL Server 交易记录文件,以及备份数据库的几种方法。在 第 33 章 中,将学习如何还原数据库、SQL Server 如何回复、以及如何建立回复计划。
备份的术语
 
在开始讨论备份技术之前,让我们回顾一些术语。在这个章节中,您将学到关于备份、还原、和回复操作的实例。
备份和还原
 
备份(backup)和还原(recover)操作相辅相成的,即保存数据库中的数据以便稍后使用,类似操作系统所执行的备份和还原作业。在备份过程中,数据从数据库中复制出来,并保存到另一个位置。操作系统备份和数据库备份是不同的,差别在于操作系统备份可以保存个别的档案,而数据库备份则保存整个数据库。通常数据库供很多的使用者共享,但是很多操作系统档案则是属于各使用者。因此,数据库备份同时备份了所有的使用者的数据。由于 SQL Server 设定了使用时间的最大值,因此不管当时使用者是否正在存取数据库,备份过程都会执行。
在还原过程中,备份数据被复制回数据库中。不要将还原(restore)和回复(回复)混淆在一起,这是两种不同的操作。和备份过程不同的是,当 SQL Server 正在执行时,还原过程无法进行。此外,数据表也无法个别还原。如果一个使用者遗失了数据库中的某些数据,遗失的数据很难还原,因为还原操作将还原整个数据库或者部分数据,而从数据库的所有数据中区分出单一使用者的数据是相当困难的。
回复
 
回复(recovery)包含用来解救系统故障的关系型数据库管理系统(RDBMS)和重新进行(回复)交易的能力。每次变更数据库时,SQL Server 并不会立即将变更写到磁盘上。如果系统每次都立即写到磁盘上,那么一个大系统(例如银行中的系统)可能会运作得相当缓慢,因为必须等待每笔交易完成写入后才能进行。这会导致交易延迟。
由于将变更内容写入磁盘时有所延迟,系统失效时可能会使数据库处于毁损状态,有些数据库的变更可能还没写到磁盘上,或是写到磁盘上的变更可能未被认可。为了保持系统的完整性,SQL Server 在交易记录文件中记录了所有的变更。(交易记录文件将在本章的 <交易记录文件> 一节中详细讨论。)系统失效后重新启动 SQL Server,它会使用交易记录文件来进行所有已经认可但没有写入磁盘的交易,并且返回故障时没有认可的交易。在这种方式中,可以保证数据的正确性。
在回复过程中,SQL Server 必须准备好处理多种类型的交易,包含以下:
•  只进行查询的交易 不需要回复。
 
•  已经变更数据库中的数据交易,以及已经认可但没有写到磁盘上 在回复过程中,SQL Server 从磁盘上读取数据页,重新套用变更,然后再将数据页写回磁盘上。
 
•  已经变更数据库中数据的交易,已经认可而且已经写到磁盘上 在回复过程中,SQL Server 确定变更已经写到磁盘上,不需要其它介入。
 
•  已经变更数据库中数据的交易,还没有认可 在回复过程中,SQL Server将使用交易记录文件,复原所有数据页上的变更,将数据库还原到交易执行前的状态。
 
当 SQL Server 从系统失效后重新启动时,回复机制将自动开启。回复机制利用交易记录文件来确定哪些交易需要回复,哪些不需要回复。很多的交易是不需要回复的,但是 SQL Server 仍必须读取交易记录文件才可做决定。SQL Server 从最后的检查点开始读取交易记录文件。(检查点将在本章的后面加以讨论。)
________________________________________
说明
由于在故障发生时,交易记录文件对于交易的回复十分重要,因此它通常保存在RAID-1(镜像)磁盘区中。(RAID 曾在 第 5 章 中讨论。)
________________________________________
在系统故障时,需要使用备份文件还原数据库(例如损毁一个磁盘),交易记录文件和交易记录文件备份用来将数据库回复到故障点。因此,还原和回复操作通常是共同作业的。在发生电力故障时,可能只需要回复。
________________________________________
说明
由 S QL Server 复原的交易等于以 ROLLBACK 指令中止交易。这个交易将被取消,而且所有的数据将还原到它的原始状态。当一个交易重新进行时,这些已经记录到数据库中但没有写入到磁盘上的数据将被重置,因此数据文件将回到故障时间的状态。也就是说,重新进行使数据库的状态返回到故障的时间点,重新处理已认可的交易,消除所有未认可的交易。
________________________________________
系统故障
 
如果使用的是如 Microsoft 丛集服务,或是磁盘具 RAID 容错功能,您可能正在怀疑是否真的需要备份,答案是「需要」。由于系统的故障方式不尽相同,容错和错误回复可能只能修正某些情况。在这一节中,我们将讨论一些潜在的故障原因,以及如何避免故障。
某些系统故障的情形可能并不严重,而另一些却可能十分严重。要了解备份的重要性,就得先了解三种主要的故障类型:硬件故障、软件故障和人为错误。
硬件故障
 
硬件故障可能是最普遍的故障类型。由于现在的计算机硬件比起之前更稳定,因此这种故障类型所发生的频率慢慢减少,但是在使用一段时间之后,组件的磨损在所难免。典型的硬件故障包括下列几种:
•   CPU、内存或总线故障 这些故障通常会导致系统损毁。在替换了有故障的组件并重新启动系统后,SQL Server 将自动执行数据库回复。数据库本身是完整的,因此并不需要进行还原,只需要回复遗失的交易。
 
•   磁盘故障 如果使用了 RAID 容错功能,那么这种故障类型可能不会影响到数据库的状态,因此只需要修复 RAID 数组。如果没有使用 RAID 容错,或是 RAID 数组发生故障,那么唯一的选择就是从备份还原数据库,然后利用交易记录文件备份回复数据库。
 
•   系统大故障或永久性服务器损失 如果系统在火灾或灾难中受到损毁,理所当然就得重新设定所有系统。硬件需要重新装配,数据库需要从备份进行还原,然后使用数据和交易记录文件备份回复数据库。
 
软件故障
 
软件故障并不常见,然而软件故障通常比硬件故障更严重。由于软件大多内建了将硬件故障影响最小化的功能,因此当软件发生故障,硬件就失去了这个保护功能,使系统更容易受到故障的影响。交易记录文件就是一个具有这种软件功能的例子,用来帮助从硬件故障进行回复。典型的软件故障包括下列几种:
•   操作系统故障 如果故障发生在 I/O 子系统中,就会破坏磁盘上的数据。如果数据库未被破坏,则只需要回复数据即可。当然,如果数据库被破坏,唯一的选择就是透过备份进行数据库还原。
 
•   RDBMS故障 SQL Server 本身是可能故障的。如果这种故障造成了损坏,那么就需要透过备份进行数据库还原和回复。如果没有损坏,利用自动回复就可以使系统返回到出现故障的那一点。
 
•   应用程序故障 应用程序也可能故障,导致数据破坏。如果这类故障造成数据的损坏,也需要透过备份进行数据库还原。反之,就不需要还原,利用自动回复将使得系统返回到出现故障的那一点即可。您可能还需要向应用程序厂商所取修补程序,以避免故障再次发生。
 
________________________________________
说明
有些公司会使用 SQL Server 的 beta 版。其实 beta 版只是用来评估和测试,不能用在一个正式的执行环境中。有时候beta版含有软件错误,包括尚未完全通过测试的功能。您应该使用 Microsoft SQL Server 2000 的产品版本,这是完全通过测试的,且供正式执行环境使用。
________________________________________
人为错误
 
第三种重要的错误类型是人为错误。人为错误可能在任何时候不经意的发生。人为的错误所造成的损坏可轻可重,麻烦的是,这类型错误很容易被忽视个几天甚至几周,使得回复更加困难。和使用者建立良好的互动关系(包括良好的通讯管道),就可以快速的回复使用者造成的错误。使用者不会害怕立即报告错误,当然越早发现错误越好。下面的故障可能是由人为错误引起的:
•   数据库服务器损失 人为错误会造成服务器故障的情形包括:不小心关闭电源、没有先关闭 SQL Server 就关闭服务器。当 SQL Server 重新启动时,回复将自动执行,当然这要花上一些时间。不过由于磁盘上的数据库未受损伤,所以不需要还原。
 
•   遗失数据 可能是有人不小心删除数据文件所造成。必须执行还原与回复操作来使数据库返回故障点前的状态。
 
•   数据表遗失或被破坏的数据 如果误删数据表,或者由于某种因素误改资料,可以使用备份和还原来将资料表返回到它的原始状态。由于遗失的单一数据表或一小组数据不能只从备份还原,因此这种故障类型的回复可能相当复杂。我们将在 第 33 章 中讨论回复这类型故障的范例。
 
SQL Server 记录文件
 
要了解备份和还原操作如何与数据库回复共同作业的,必须先了解 SQL Server记录文件的运作方式。这一节将提供关于 SQL Server 记录和检查点的概述,并将告诉您如何备份交易记录文件。
交易记录文件
 
 交易记录文件 (transaction log)用来记录所有的交易以及这些交易对数据库做出的修改。这个记录让回复可以进行。当认可一个交易时,只要认可记录还没写入交易记录文件,认可操作就不算完成。由于对于数据库的变更并不需要立即写入磁盘中,这个记录文件只是一种在系统故障事件中可以回复交易的方法。
________________________________________
说明
如果一个数据文件受到损坏必须透过备份还原时,所有发生在这个数据文件上的交易都必须重复执行一次,才能将数据库回复到故障的那一点。由于交易记录文件是这个过程的关键,而且空间有限,所以必须执行交易记录文件备份。您必须保存从上次备份到现在产生的所有交易记录数据,这样才能回复数据库。如果您只对上一次备份的还原感兴趣,您可以跳过交易记录文件备份,但是目前的交易记录文件将不能回复那次备份以后发生的交易。
________________________________________
延迟写入器执行绪
 
在数据库上的变更是最先写入 SQL Server 快取区中的资料。变更快取区中的数据主要是为了提升效能,因为等待 I/O 运作是相当费时的。这些变更最终还是会写入磁盘,只是这个过程在背景执行,而使用者并不知道。由于修改的页面储存在快取区,在这些页面(称为Dirty分页)被 SQL Server 执行绪写入磁盘之前,会耗费相当大量的时间。这个执行绪称为 延迟写入器执行绪 (lazywriter thread).
延迟写入器执行绪使用近来最少使用的页面清单,这表示近来最少使用的数据将放在写入磁盘的清单开头,而刚刚才被使用的数据放在清单结尾,而且也最不可能被写入磁盘中。那些经常被修改的页面(因此总是不断地被移到清单的结尾)可能永远不会被延迟写入器执行绪写入磁盘中。这样会增加回复时间,因为可能必须读取许多交易记录才能将所有的变更应用在数据上。
例如,在一个具有超过 1 GB 的 RAM 的大规模系统中,要对数据库做很多变更的话,回复过程将花费好几个小时。除了延迟写入器执行绪之外,检查点(checkpoint)执行绪也将 Dirty 页面写入到磁盘中。(我们将在本节的后面详细讨论检查点执行绪。)
顺序记录
 
因为交易记录文件是交易的历史记录,交易记录文件的 I/O 运作主要是写入,并且一般是按照时间顺序。在交易复原事件中,交易记录文件将被读取,且 I/O 的时间顺序将被破坏。由于复原相当少见(因为系统崩溃很少见,而且使用者不会常常复原交易),交易记录文件中的 I/O 模式相当稳定。您可将交易记录文件放在它自己的磁盘或 RAID 数组中来增强 I/O 效能,就像 第 4 章 和 第 5 章 讨论过的。您应该使用 RAID 保护交易记录文件,因为这些交易纪录对于数据库回复是很重要的。
交易记录文件大小
 
根据对数据库的变更数量,交易记录文件可能增长得很大。因为交易记录文件是一个或多个档案的有限集合,最终它将被填满,因此必须定期删减。完成记录文件备份时,记录文件会自动被删减,这将在本章的后面讨论。
________________________________________
说明
如果没有备份记录文件,您还是可以删减这个记录文件,只要将数据库的数据库选项 trunc.log on chkpt 设为 TRUE 就行了。然而,这样做以后您便不能备份交易记录文件。这个设定将使得数据库不可回复,因此不建议使用。
________________________________________
使用交易记录文件回复
 
在数据库档案没有破坏的系统故障事件中,当前的交易记录文件可以用来回复数据库,因为只需要回复那些还没有写入到磁盘中的交易。必须回复的页面数量取决于数据库中的 dirty page 数量,由检查点间隔决定。检查点会将 dirty page 写入磁盘中,减少执行回复的时间。检查点和检查点间隔将在本章的 <检查点> 一节中详细讨论。
交易记录属性
 
SQL Server 2000 和 SQL Server 7.0 中的交易记录文件有很多相同的特点,如下:
•  交易记录文件不再被视为等同于一个资料文件。在 8KB 页面中交易不会像数据文件一样从交易档案中被写入或读取。现在交易记录文件可以写在任何它需要的大小尺寸中,交易记录文件页面不再按照数据页的格式。因此,如果记录文件写入执行绪只需写入少量内容,它就不必写 8 KB 的资料。如果系统经常更新,那么记录文件写入执行绪可以使用大型区块(16 KB、32 KB等)来写入。
 
•  交易记录文件可以依据需要设定为自动增长。这个特性允许在需要时增加更多的空间,但是在使用它时应该注意避免交易记录文件的无限制增长而占用整个磁盘。
 
•  现在交易记录文件可以用多个档案来建置。这些档案也可以设定为自动增长。但是交易记录档案无法划分成数据带;它们要一个接着一个使用。(数据带划分在 第 5 章 中讨论。)
 
•  交易记录文件可以移到其它系统中使用,以便在备用系统中再度执行。这就是所谓的记录转移,将在下一章中有更多的讨论。
 
无纪录操作
 
您已经熟悉纪录和回复的规则,可以开始学这些规则的例外情形。如之前所提到,在正常的情况下,所有交易以及变更都记录在交易记录文件中。然而,您可以执行某些不会记录下来的操作。这些操作称为非记录作业(nonlogged operation)。使用非记录作业来执行大量数据操作(占用大量的交易记录档案资源)时,可以提升操作效能。
由于非记录作业没有记录在交易记录文件中,如果有必要回复数据库的话,就必须重新操作一次。因此,在使用非记录作业前,必须仔细考虑非记录作业的影响结果。非记录作业的执行方法如下:
•  SELECT INTO
 
•  BULK COPY and Bulk Copy Program (BCP)
 
•  CREATE INDEX
 
•  特定文字操作
 
本章稍后会谈到上述操作的更多细节。
为了让数据库中可以执行非记录作业,必须将数据库设定在 BULK_LOGGED 回复模式。其它的回复操作是 FULL 和 SIMPLE。使用 ALTER DATABASE 指令设定这些选项,如下:
ALTER DATABASE Northwind
SET RECOVERY BULK_LOGGED

ALTER DATABASE Northwind
SET RECOVERY FULL

ALTER DATABASE Northwind
SET RECOVERY SIMPLE
使用 BULKED_LOGGED 回复模式时,本章所提的大量操作将不会有记录(会有些例外情形,将在稍后说明),而其它操作仍会有记录。如果选择 FULL 回复模式,那么所有的操作又会全部记录下来。当执行SIMPLE回复模式时,数据只会回复到最后一次备份。
________________________________________
说明
因为回复模式限定您的系统的故障容忍度,所以使用 BULK_LOGGED 回复模式时必须很谨慎。如果您使用这个模式,可以提升非记录大量操作的效能,但是故障事件发生时,将会增加回复时间。
________________________________________
SELECT INTO
 
SELECT INTO 陈述式是用来在数据库中建立新的数据表。因为 SELECT INTO陈述式不能用来选择数据放入已存在的对象中,所以它不能用来更新数据,只能用来建立数据。建立数据的过程常常可以重复执行,因此 SELECT INTO 陈述式很适合用来执行非记录作业。
大量复制和 BCP
 
为了使大量复制和 BCP 操作可用来执行非记录作业,必须符合下列几项要求:
•  数据库选项 select into/bulkcopy 必须设定在TRUE。
 
•  当大量数据复制开始时,目标数据表必须是空的才能够制作索引。
 
•  不能复制目标数据表,因为交易复制时占用了交易记录文件中复制数据时所需要的项目。
 
•  必须指定 TABLOCK 提示来强制锁定数据表。
 
这些限制让大量复制操作节省交易记录文件的空间,还让执行速度变快。然而,当数据库必须从备份还原时,这些非记录作业都要重新操作一次。
CREATE INDEX
 
CREATE INDEX 陈述式操作使也很适合执行非记录作业,因为索引可以依需要重新建立。重建索引并不困难。然而,如果数据表太大,过程可能会相当花费时间,并占用资源。
文字操作
 
文字操作可以用来执行非记录作业的是 WRITETEXT 和 UPDATETEXT。要使这些操作执行时不留下记录,您只要像刚刚所提的使用 BULK_LOGGED 回复选项就可以了。
检查点
 
检查点(checkpoint)是用来使实体数据文件和数据库快取的状态同步的操作,可以减少系统故障事件发生时的必要回复时间。回复数据库需要的时间取决于最后一个检查点以来的时间总量和缓冲快取区中的 dirty page 数量。因此,减少检查点的间隔可以减少回复时间,但会增加系统负荷:检查点过程会导致大量的系统资源占用。
检查点发生在以下时间点:使用 CHECKPOINT 陈述式时、使用 SHUTDOWN陈述式关闭 SQL Server 时、使用服务管理员关闭 SQL Server 时,以及 SQL Server 自动产生检查点时。
检查点操作
 
检查点过程执行数个操作,包括下列内容:
•   在检查点开始时就将所有的dirty page写出 这时所有包含已变更数据但尚未写到磁盘中的页面将被写到磁盘中。
 
•   将未完成的交易清单写到交易记录文件中 告诉 SQL Server 在检查点发生时进行了哪些交易。如果系统发生故障,回复过程将使用这个数据回复交易。
 
•   将所有的 Dirty 记录文件分页写到磁盘中 确保记录文件缓冲区会更新到磁盘中。
 
•   将检查点记录储存到数据库中 由于交易记录文件会被备份并删减,所以需要在交易记录文件以外保留一个检查点的记录。
 
设定检查点间隔
 
检查点间隔由 SQL Server 设定选项 复原间隔 定义。这个组态选项为整个SQL Server 系统设定,不是为单个数据库设定,但检查点在每个数据库都会执行。这个组态选项指定了 SQL Server 在系统故障时用来回复每个数据库的分钟数。默认值为 0,指示 SQL Server 为您确定检查点间隔,通常小于一分钟。对于拥有海量存储器和大量插入以及更新行为的系统,这个默认值可能导致过多的检查点数量。在这种情况下,您可以将这个组态选项设定为较大的值。如果您的使用者可以容忍系统故障时,花费较长的回复时间(例如 30 分钟),那么您系统上的交易效能将会提升。您应该根据您掌控停机时间的能力和故障的频率来设定这个组态选项。
检查点间隔还取决于交易记录文件中的记录数量。它不由系统时间或记录文件大小来决定。交易记录文件中的记录越多,检查点间隔越短。做出的变更越多,插入到交易记录文件中的记录也就越多,从而导致 SQL Server 设定检查点间隔时必须经常将变更写入磁盘。如果数据库的变更很少甚至没有的话,那么交易记录文件将只包含很少的记录,检查点间隔将会变长。
复原间隔组态选项可以透过两个途径变更:使用 Enterprise Manager 或使用T-SQL。要从 Enterprise Manager 中设定复原间隔,请在左边窗格中在需要设定这个组态选项的服务器名称上按鼠标右钮,从快捷菜单中选择 内容 进入 SQL Server 属性窗口。选择 数据库设定 页签,如图32-1所示,在复原间隔选择方块中指定需要的复原间隔,单位为分钟。

 
 
图32-1 SQL Server属性窗口
要使用 T-SQL 设定复原间隔,请使用 sp_configure 预存程序,如下所示:
sp_configure "recovery interval", 1
GO
您将看到下面的输出:
DBCC execution completed. If DBCC printed error messages,
contact your system administrator.
Configuration option changed. Run the RECONFIGURE statement
to install.
在执行 RECONFIGURE 命令前,这个变更不会生效。如果确认变更,请键入下面的 T-SQL 陈述式:
RECONFIGURE
GO
RECONFIGURE 命令发出信号给 SQL Server,让它接受设定的变更。不需要为了改变复原间隔组态选项使之生效而重新启动 SQL Server。要确保您的设定确实生效,请使用下面的 T-SQL 陈述式:
sp_configure "recovery interval"
GO
输出看起来像这样:
name      minimum  maximum   config_value   run_value
-------------------------  -------  -------   ------------   ---------  
reconvery  interval (min)  0        32767     1              1
可以看到到复原间隔组态选项已被设定。
________________________________________
注意
复原间隔组态选项是进阶选项,只有在仔细规划后才能变更。增加复原间隔设定将增加执行数据库回复时需要的时间。
________________________________________
备份方法
 
有数种备份数据库的方法:完全备份、差异备份、交易记录文件备份、档案群组备份和数据文件备份。每种方法都有它自己的操作方式和功能。完全备份(full backup)备份数据库、档案群组或数据文件中的所有数据。差异备份(differential backup)只备份那些自上次备份以来变更过的资料。交易记录文件备份(transaction log backup)用来备份和删减交易记录文件。(正如我们所见,备份交易记录文件是很重要的 DBA 任务,因为交易记录数据是用来和数据库备份连结的)档案群组备份(File群组 backup)和数据文件备份(datafile backup)用来备份数据库中特定的档案群组或数据文件。
所有的 SQL Server 备份都对特定的数据库执行。要完成备份,您应该备份系统中的所有数据库和它们的交易记录文件。不要忘记备份 master 数据库。记住,没有一个好的备份,在出现故障事件时,您就不可能还原您的数据。
完全备份
 
前面已经提到,完全备份将备份一个完整的数据库。将备份所有作为数据库一部分的档案群组和数据文件。如果您有多个数据库,您应该备份所有的数据库。对于备份小规模的数据库,完全备份可能是最普遍的技术。根据数据库的大小,整个过程可能相当的占用时间。因此,如果时间成为问题,您可能应该考虑执行差异备份或档案群组备份,这将在后面讨论。您一旦开始备份,就没有办法将它暂停,备份过程将一直继续到整个数据库完成备份。我们将在稍后 <执行备份> 一节讨论完全备份的执行。
差异备份
 
差异备份只备份那些自上次备份以来修改过的信息。由于它们只备份一部分数据,差异备份比完全备份速度快,而且占用较少的空间。然而差异备份的还原比完全备份更困难、也更花费时间。还原差异备份需要最近完全备份的还原,所有差异备份都自上次完全备份后产生。
交易记录文件备份
 
交易记录文件备份使您能够备份交易记录文件。正如在本章前面所述,这些备份对于数据库回复很重要。
档案群组备份
 
档案群组备份将备份与数据库中的单一档案有关的所有数据文件。这个过程和完全备份类似,它将备份数据文件中所有的数据,而不考虑数据上次备份的时间。您可以根据系统设定,使用档案群组备份来备份和特定的部门或工作群组有关联的档案群组。如果您的系统分成各个独立部门的数据并存取它们自己的档案群组,您可以按照不同的排程来分别备份每个部门的数据。
数据文件备份
 
数据文件备份使您能备份文件群组中的单一档案。这种备份类型和 SQL Server 2000 分别还原单一数据文件的能力一起运作。如果您每晚没有足够的时间备份整个档案群组,那么数据文件备份会十分好用,它允许您循环备份数据文件。当磁盘故障事件发生时,有某个数据文件遗失或受到破坏,您只需还原这个特定的数据文件。然而数据文件备份的时间越久,还原过程所花的时间会越长。
执行备份
 
您可以使用 Enterprise Manager、T-SQL 指令或 Create Database Backup Wizard来执行备份。Create Database Backup Wizard 方法是这些方法中最简单的,但是 Enterprise Manager 也是很容易使用的。另一方面,T-SQL 指令可以放置到 SQL 指令文件中,这样就可以重复使用。应该使用最合乎您需要的方法。
备份操作自身可以导向到实体装置或逻辑装置中。实体装置(physical device)是如磁带机或磁盘驱动器的对象。实体装置透过操作系统分配名称,而您必须使用这些名称来存取这些装置。由于这些预先分配的名称很难记住,您可能想要为实体装置建立一个别名或使用者自订名称。这样的别名就被称为逻辑装置(logical device)。这些的逻辑装置只存在于 SQL Server 中,并且只能由 SQL Sever 备份使用,因此也可以将它视为逻辑备份装置(logical backup device)。如果您要将数据备份到逻辑装置上,您必须预先建立这个装置。在我们讨论执行备份的不同方法之前,让我们先看看如何建立逻辑备份装置。我们将使用一个逻辑备份装置作为本节的例子。(参见系统管理员中关于在系统中增加实体装置的详细内容。)
建立逻辑备份装置
 
逻辑备份装置的建立有两种方法:使用 Enterprise Manager 或 T-SQL。我们将在本节中讨论这两种技术。多个备份装置的使用可以改善效能。(在本章的 <改善备份> 一节中将提供备份效能的提示。)
使用 Enterprise Manager 建立备份装置
 
要使用 Enterprise Manager 建立备份装置的方法如下:
1. 在 Enterprise Manager 左边窗格中展开 SQL Server 群组数据夹、Server 数据夹和 管理 数据夹。
2. 在 备份 上按鼠标右钮,然后从快捷菜单中选择 新增备份装置 ,进入 备份装置属性 窗口,如图32-2所示。
 
 
图32-2 「备份装置属性」窗口
3. 只要在 名字 文字方块中键入备份装置的描述性名称, 文件名称 文字方块就会自动填入。要变更文件名称路径,可以在 文件名称 文字方块中键入新的路径,或者点选 浏览 按钮打开 备份装置位置 对话框。本例中,备份装置的名称是 Backup_dev_1。如果要增加一个磁带装置,按下 检视内容 按钮,以检视当前在磁带装置中的备份集合。
一旦完成了这些步骤,这个装置就已经可以使用了。在学习如何建立备份过程中,我们还要学习如何使用备份装置。注意,如果您没有任何连接到您的系统的磁带装置,就不能使用 磁带装置名称 选项。
使用 T-SQL 建立备份装置
 
要使用 T-SQL 建立一个备份装置,请使用预存程序 sp_addump-device。sp_addumpdevice的语法如下:
sp_addumpdevice device_type, logical_name, physical_name
device_type 组态选项可以是 disk、tape 或 pipe,分别表示磁盘、磁带机和连接协力厂商软件到备份系统中。logical_name 组态选项是您分配给这个装置的名称;这个名称可在 BACKUP 和还原陈述式中引用。physical_name 组态选项是系统分配的装置或文件名称。
例如,要建立一个名为 Backup_dev_2 磁盘档案的逻辑装置,请使用下面的语法:
sp_addumpdevice 'disk', 'Backup_dev_2',
'C:/MSSQL7/BACKUP/Backup_dev_2.BAK'
建立远程备份装置
 
为了将数据库备份到远程系统,您必须先使用系统预存程序 sp_addumpdevice来建立备份装置。您不能在远程服务器上用 Enterprise Manager 建立备份装置。为了指定远程系统,您必须像实体名称一样指定 Universal Naming Convention (UNC)的全名,如下例所示:
sp_addumpdevice 'disk', 'netbackup1',
'//ptc4/c$/backup/netbackup1.bck'
一旦建立了这个备份装置,您就能够使用 Enterprise Manager 或者 T-SQL 陈述式来将数据备份进去。
________________________________________
说明
将数据备份到远程系统上,您必须先安装 SQL Server 来执行。如果在LocalSystem 账号之下执行,LocalSystem 账号没有存取远程系统的权利,会使得备份失败。
________________________________________
透过多重网络备份数据
 
您也可以透过多重网络适配卡来执行备份。透过好几个 LAN 程序段将数据备份到多重装置上,您可以克服可能限制效能的网络频宽问题。如果您正好透过两个 LAN 程序段来将数据备份到一个系统上,您就可以在 UNC 地址上指定 IP 地址,如下所示:
sp_addumpdevice 'disk', 'netbackup1',
'//100.100.100.1/c$/backup/netbackup1.bck'
sp_addumpdevice 'disk', 'netbackup2',
'//100.100.200.1/c$/backup/netbackup2.bck'
建立了这个备份装置,您就能够使用 Enterprise Manager 或 T-SQL 指令将数据备份在里面。
使用 Enterprise Manager 备份
 
在您建立了一个或多个备份装置后,您已经可以开始执行备份了。我们将首先讨论 Enterprise Manager 方法。为了避免重复,有些交易记录文件和数据库备份方法将放在一起讨论,其中可辨识两者差别的特定选项将会特别提出说明。
执行备份
 
要使用 Enterprise Manager 执行备份,请按照下面的步骤:
1. 要呼叫 SQL Server Backup 工具,请使用下面的技术之一:
o 在 Enterprise Manager 的左边窗格中展开一个服务器,然后展开管理数据夹。在 备份 上点选鼠标右钮,并从快捷菜单中选择 备份数据表 。
 
o 在 Enterprise Manager 的左边窗格中展开一个服务器,然后在 数据库 上点选鼠标右钮,并从快捷菜单中选择 所有工作 ,接着选择 备份数据表 。
 
o 在 Enterprise Manager 的左边窗格中展开一个服务器,然后点选 数据库 数据夹。在右边窗格中的一个数据库上点选鼠标右钮,并从快捷菜单中选择 所有工作 ,接着选择 备份数据库 。这时将出现 SQL Server 备份窗口,如图32-3所示。
 

 
 
图32-3 SQL Server 备份窗口的一般页签
2. 在 数据库 下拉式清单中对话框的顶部区域,选取您要备份的数据库。(如果您在第一步骤中使用第三种技术,那么就已经选择了数据库的名称。)备份的名称会依据数据库的名称自动产生,可以在 名称 文字方块中键入一个备份的名称来覆写自动产生的名称。也可以在 描述 文字方块中键入一个备份说明。在您试着还原数据库时,这个说明可能会很重要。例如,如果您在删除一个数据表前立即建立了这个备份,则这个备份说明中的批注将十分有用。如果您在加载新的数据前执行备份,请将这信息包含在您的说明中。
3. 在这个对话框的 备份 区域中,必须指定执行备份的类型。可用选项将根据选择的数据库而有所不同。例如,Northwind 数据库预设 Truncate Log On Checkpoint 选项,设定这个选项会让备份程序无法使用 Transaction Log 和 File And File 群组选项。这些备份选项说明如下:
o  数据库 - 完整备份 执行一个完全数据库备份;将备份数据库中的所有数据。
 
o  数据库 - 差异备份 执行一个差异数据库备份;将备份自上次备份以来变更的所有数据。
 
o  交易记录文件 执行一个交易记录文件备份;它将同时删减这个记录文件。
 
o  档案及档案群组 备份单一档案群组或档案;您可以指定备份的档案群组或档案。
 
只能选择其中一种备份类型。要执行完全数据库备份和交易记录文件备份,您必须执行两次备份程序。
4. 在 目的地 区域,必须指定备份是到磁带还是磁盘上。点选 新增 ,可以加入更多的逻辑或实体备份装置。这时将出现 选取备份目的 对话框,如图32-4所示。在这个对话框中,您可以指定一个文件名称或从 Backup Device 下拉式清单中选取备份装置。点选 确定 ,返回一般页签。在图32-3的例子中,在 Backup To 清单中列出了两个装置。要删除一个装置,请在选择该装置后,点选 移除 。点选 内容 来检视装置的内容。
 
 
图32-4 选取备份目的对话框
如果一个备份装置先前已经使用过,就可使用信息是可用的:
o  名称 这个名称由曾经执行备份的使用者选择过。
 
o  服务器 曾经执行备份的服务器的名称。
 
o  数据库 曾经执行备份的数据库的名称。
 
o  类型 备份的类型(完全、差异、档案群组、档案)。
 
o  日期 备份执行的日期和时间。
 
o  到期时间 该备份指定的到期时间。
 
o  规模 备份集合的总规模。
 
o  描述 备份的说明。
 
记住,多个备份经常能够执行到同一备份装置中。
5. 在 SQL Server Backup 对话框中的 Overwrite 区域,您可以选择覆写(overwrite)媒体(如磁带、磁盘)或者附加(append)媒体。磁盘装置通常是使用附加。但是如果您正在使用磁带,并循环使用旧的磁带,您需要删除以前的信息。虽然您可以在对话框中点选 Overwrite Existing Media 来覆写那些信息,但较好的习惯是在执行备份前先清除那些信息。采取这个预防措施有助于确保不会意外地覆写了一个磁带或磁盘装置。
6. 在 排程 区域中,可以选择稍晚才来排程备份。排程备份对于交易记录文件备份特别有用,这种类型的备份必须按照一定的时间来执行,以避免交易记录文件被填满。如果您要排程备份,选取 排程 复选框,然后点选 ... 按钮来显示 编辑排程 对话框,如图32-5所示。
7. 在 名称 文字方块中,为每个排程提供一个名称。排程的命名允许您建立多个排程(也许是每个备份一个排程)。
在 排程类型 区域中,您可以指定在 SQL Server 代理程序启动时是否自动启动备份、是否只要 CPU 闲置就启动备份、以及备份是否只执行一次或是将反复执行。如果您选择执行一次备份,您可以使用 日期 来选择备份执行日期,并使用 时间 选择方块来选择时间。

 
 
图32-5 编辑排程对话框
要设定循环备份的排程,请点选 重复执行 和 变更 。这时将出现 编辑执行作业排程 对话框,如图32-6所示。
这个对话框提供您极好的排程灵活度。在 每天 、 每周 和 每月 选项中,可以安排每个工作的频率和持续时间。

 
 
图32-6 编辑执行作业排程对话框
8. 点选 确定 返回 编辑排程 对话框,再次点选 确定 返回 SQL Server备份对话框,然后点选 选项 页签,如图32-7所示。在这个页签中,可以指定是否应该在备份完成时确认备份媒体,并指定是否要标示以及如何标示这个媒体。可用的选项如下所述:
o  完成时确认备份 确认备份媒体是否可读取。只确认媒体的完整性;过程中不确认资料是否已经备份。
 
o  备份后退出磁带 在备份完成后,将磁带从磁带装置中退出。当多个应用程序或使用者正在存取磁带装置时,该选项是有用的。这个选项可以避免您的磁带被其它人覆写。
 
o  移除交易记录文件中不使用的项目 在备份后删减交易记录文件。
 
o  Check Media Set Name And Backup Set Expiration 指定媒体要被检查,并在到期前不被覆写。
 
o  检查媒体集名称及备份集是否逾期 允许设定媒体的到期日期。
 
o  备份及逾期时间 允许为媒体指定一个标示。
 

 
 
图32-7 SQL Server 备份对话框的选项页签
9. 完成这些选项的设定后,点选 确定 ,开始执行所设定的备份。
管理备份
 
要检视、删除和修改您已经安排的备份工作,请按照下列步骤:
1. 在 Enterprise Manager 的左边窗格中,展开一个服务器数据夹,展开管理数据夹,展开 SQL Server 代理程序数据夹,并点选 作业 。这时已经安排的工作会列在 Enterprise Manager 的右侧窗格中,如图32-8所示。
 
 
图32-8 Enterprise Manager 作业显示
2. 要删除一个作业,只要在作业名称上按鼠标右钮,并从快捷菜单中选择 删除 。
3. 要检视或修改一个作业,在工作名称上按鼠标右钮,并从快捷菜单中选择 内容 来显示属性窗口。执行您的修改,然后点选 套用 和 确定 。
使用 T-SQL 指令备份
 
刚开始使用 T-SQL 备份数据库比使用 Enterprise Manager 稍微难一些,但是如果您属于那种喜欢使用指令文件自动执行操作的 DBA 类型,那么这种技术应该也是您所喜欢的。TSQL BACKUP 指令也提供比在 Enterprise Manager 中的备份程序还要多的选项。本节中我们将讨论 BACKUP 指令的语法和选项。实际上有两种 T-SQL 备份指令,使用时依照您所要执行备份的类型而定。这些指令如下:
•   BACKUP DATABASE 用来备份整个数据库、档案或档案群组。
 
•   BACKUP LOG 用来备份交易记录文件。
 
因为这两种指令大部分共享相同的选项,所以我们将它们放在一起讨论。
执行备份
 
用来进行完全数据库备份的 BACKUP 陈述式语法如下:
BACKUP DATABASE database_name
TO backup_device
[ WITH options ]
这个陈述式只需要数据库名称、文件名称或档案群组名称和备份装置名称。可以包括多个文件名称或档案群组名称,中间以逗号隔开。
交易记录文件备份的陈述式语法如下:
BACKUP LOG database_name
{
[ WITH { NO_LOG | TRUNCATE_ONLY )]
}
|
{
TO backup_device
}
[ WITH options ]
这个陈述式需要数据库名称、WITH NO_LOG 或 WITH TRUN-CATE_ONLY 选项、或者是备份装置名称,然后您可以加入任何您需要的选项。NO_LOG 和 TRUNCATEONLY 选项是同义的,都将只删减记录文件,而不使用备份拷贝。
________________________________________
注意
在系统故障事件中,如果使用 BACKUP LOG 陈述式中的任何一个选项,您都将无法将数据库回复到故障点,因为没有记录文件会保存下来。不建议使用这两个选项,使用它们需要您自己承担风险。
________________________________________
在所有的三个备份指令中,database_name 是您要执行备份的数据库名称。backup_device 组态选项可以是一个逻辑备份装置名称或是实体装置名称。如果指定为实体装置,就要根据装置类型来为装置名称加上前置字 DISK=、TAPE= 或 PIPE=。您可以指定一个装置或用逗号隔开的一组装置,如下面两个例子所示:
Backup_dev_1, Backup_dev_2, Backup_dev_3

TAPE = '//./Tape0', TAPE = '//./Tape1', TAPE = '//./Tape2'
选项
 
表32-1 列出了 BACKUP 指令可用的选项。如果某个选项只能对数据库备份或记录文件备份所用,将会对这些例外作批注。
表32-1 BACKUP 指令选项
选项  描述
BLOCKSIZE 实体区块大小,单位为字节。
DESCRIPTION 指定备份集合的文字说明。对于还原时定位正确的备份集合十分有用。
DIFFERENTIAL 指定一个差异备份。这个选项只在使用完全数据库备份有用。
EXPIREDATE = date |
RETAINDAYS = days EXPIREDATE 选项指定备份集合到期的日期(可以被覆写)。RETAINDAYS 选项指定备份集合到期前的天数。
PASSWORD = password 指定备份的密码。提供备份本身较大的安全性。
FORMAT | NOFORMAT FORMAT 选项指定媒体标题将被重写,因此会使媒体中的原始数据无效。NOFORMAT 指定媒体标题将不被重写。
INIT | NOINIT INIT 选项指定备份集合位于媒体的第一个档案中并保存媒体标题,但覆写媒体中的所有数据。也就是说,INIT覆写在磁带上的任何内容。NOINIT 选项指定备份附加到媒体中。如果您要重新使用磁带,您将需要使用这个选项。
MEDIADESCRIPTION = text 设定媒体集合的说明。
MEDIANAME = media_name 指定媒体的名称。
MEDIAPASSWORD = password 指定媒体集合的密码
NAME = backup_set_name 设定备份集合名称
NOSKIP | SKIP NOSKIP 选项指定在备份集合被覆写前,检查媒体中备份集合的到期日期。SKIP 选项不检查到期日期。
NO_TRUNCATE 指定在备份后不删减交易记录文件。这个选项只在记录文件备份中有用。
NOUNLOAD | UNLOAD NOUNLOAD 选项指定在完成备份后,媒体不被卸载(例如,不退出磁带)。UNLOAD 选项指定在完成备份后,卸载媒体。
RESTART 指示 SQL Server 重新启动被中断的备份。
STATS [ = percentage ] 在完成指定备份的百分率后,显示一个讯息。如果您想要检视操作的过程,这个选项将会是有用的。
请确认您指定了备份附加到媒体中,或是应该覆写媒体;您选择的选项会影响到写入磁带中数据的数量。如果您正要备份数据到一个已经使用过的磁带装置上,却没有清除这个磁带,也没有指定要覆写磁带,您将发现磁带的空间很快就用完了。在附加模式中,备份程序将只使用磁带末端的可用空间。
________________________________________
真实世界 使用BACKUP
这里有一些使用 BACKUP T-SQL 指令的例子。
下面的例子为 Example 数据库备份数据文件:
BACKUP DATABASE Example
TO Backup_Dev_1, Backup_Dev_2
WITH
DESCRIPTION = "DB backup of example",
STATS = 5
GO
备份装置是 Backup_Dev_1 和 Backup_Dev_2,并当每完成备份的 5% 就会显示统计数字。注意,在先前的例子中提供备份的说明。
如果您在一个小的数据库上测试这个例子,例如 Northwind,您看到的统计数字并不是 5% 的增量,您可能看到如 7%、16% 等的增量。这种差异的出现是因为备份程序一次读取和写入大于整个备份的 5%,这时就显示那些较大的增量。对于较大的数据集合,写入的增量将比 5% 小,所以将按照预设的显示。
下面的陈述式将备份 Example 数据库的交易记录文件:
BACKUP LOG Example
TO Backup_Dev_3, Backup_Dev_4
WITH
DESCRIPTION = "DB backup of example",
STATS = 25
GO
备份装置是 Backup_Dev_3 和 Backup_Dev_4,统计数字将显示出 25% 的间隔时间。输出结果显示已完成操作和备份结果的百分率。您将会被通知备份了多少页面、备份花了多长时间、以及备份的速度(MB/sec)。
________________________________________
管理备份
 
因为 T-SQL 指令 BACKUP 不在 Enterprise Manger 下执行,因此不能在 SQL Server Agent 下执行,所以您不能透过 BACKUP 指令来排程一个工作。然而您可以使用 SQL Server 排程功能来排程一个 T-SQL BACKUP 指令。一旦排程了这个工作,就能够和管理 Enterprise Manager 备份一样来管理这个工作了。
使用建立数据库备份精灵
 
现在让我们进入第三种执行备份的方法:使用建立数据库备份精灵。
执行备份
 
要使用建立数据库备份精灵来执行一个备份,请按照下列步骤:
1. 在 Enterprise Manager 中,点选您要建立备份的数据库,然后从 工具 菜单中选择 精灵 ,显示 选择精灵 对话框。在 选择精灵 对话框中展开 管理 数据夹,选择 备份精灵 ,接着点选 确定 。此时出现 欢迎使用数据库备份精灵 画面,如图32-9所示。
 
 
图32-9 欢迎使用数据库备份精灵画面
2. 点选 下一步 进入 选取要备份的数据库 画面,如图32-10所示。在这个画面中,指定将要备份的数据库。图32-10显示所选的 Northwind 数据库。
 
 
图32-10 选取要备份的数据库画面
3. 点选 下一步 进入 输入备份的名称及描述 画面,如图32-11所示。提供备份集合的名称和说明,在 名称 的文字方块中键入名称,在 描述 的文字方块中键入说明。如果拥有很多备份,建议键入一些说明。
 
 
图32-11 输入备份的名称及描述画面
4. 点选 下一步 进入 选取备份类型 画面,如图32-12所示。选择想要执行备份的类型: 备份整个数据库、差异式数据库备份 或 交易记录文件备份 。图32-12显示选择的是 备份整个数据库 。
 
 
图32-12 选取备份类型画面
5. 点选 下一步 进入 选取备份目的地及动作 画面,如图32-13所示。在 选取备份装置 区域中,指定是否要备份数据到磁带、档案或是一个特定备份装置上,如果需要的话,请在适当的文字方块中键入文件名称或装置名称。在 属性 区域中,指定是否应该覆写或附加备份媒体,在备份后是否要弹出磁带(如果您使用磁带),以及是否应该确认备份的完整性。确认备份的完整性是很好的主意,因为坏的磁带可能导致整个备份失效。SQL Server 透过读取磁带并确认所有数据是可读取的来确认备份的完整性。
________________________________________
说明
建立数据库备份精灵只允许选择一个备份装置,这将彻底影响到备份效能,我们在本章的 <改善备份> 一节中看到。由于这个原因,Enterprise Manager 备份方法比建立数据库备份精灵更适合使用。
________________________________________

 
 
图32-13 选取备份目的地及动作画面
6. 点选 下一步 进入 备份确认与排程 画面,如图32-14所示。这里有确认媒体标示和设定到期日期的选项,如在 <使用Enterprise Manager备份> 一节中的说明。您也可以使用 编辑排程 对话框来将备份排程在稍后的时间执行,前面曾说明过(如图32-5所示)。
 
 
图32-14 备份确认与排程画面
7. 点选 下一步 进入 完成建立数据库备份精灵 画面,如图32-15所示。检查文字方块中的信息,并点选 Finish 来执行这个备份。
 
 
图32-15 完成建立数据库备份精灵画面
管理备份
 
如果使用建立数据库备份精灵,只能执行备份或建立一个定期的备份作业。如果建立了一项作业,必须使用 Enterprise Manager 或 T-SQL 来管理作业。管理作业在本章的 <使用Enterprise Manager备份> 一节中已经简要说明。
追踪备份
 
当您执行一个备份时,不管是透过 Enterprise Manager、T-SQL 或建立数据库备份精灵,都将保存一个备份的记录。这个记录作为一列储存在 msdb 数据库的 backupfile 数据表中。在数据库回复时,这些信息用来确定数据库是在何时执行的最后一次备份。其它信息,例如备份集合 ID、被备份的文件名称等等也被储存。因此系统数据库定期进行备份是很重要的,这样在需要时,便能够获得回复的信息。
排程备份
 
排程备份是非常主观的任务。很多因素将会影响到设计备份排程。由于在备份过程中,系统效能将会降低,所以备份应该限制在业余时间进行。在本节中,我们将回顾几个诀窍,这些诀窍可以帮助您设定一个备份排程。记住,即使备份影响了系统的效能,它们仍然是必须进行的关键操作,它们可以防止系统出现数据丢失。
备份排程秘诀
 
下面的诀窍可以协助您决定系统的理想备份排程:
•   计划完全备份在业余时间进行 如果您的公司不是 在7-by-24 环境(每周7天,每天24小时)中执行,那么业余时间将是执行备份的最佳时间。
 
•   每隔几天做一次完全备份排程 如果您的数据库很大,而您不能在指定的时间执行完全备份,那就将备份操作分成几个区块。每次您可以执行数据库中一个区块的档案或档案群组备份。几天之后您就备份了所有的数据。
 
•   使用差异备份 如果您不能每晚都提供时间来执行完全备份,那么您可以在一周中执行差异备份,在周末的时候执行完全备份。
 
•   自订备份计划 每个系统都是不同的,每个公司也都是不同的。设计最能符合您需要的备份排程。
 
________________________________________
 真实世界 规划备份
这里有几个备份规划的范例,可能有助于您开发您自己的备份排程:
•  5-by-8环境中的小系统 这种类型的系统通常允许每晚的完全备份。根据交易记录文件的大小和完成的交易数量,交易记录文件每天只需备份一次。
 
•  7-by-24环境中的中等规模系统 执行在 7-by-24 环境的中等规模系统不允许大量备份的停机时间。然而,如果您的系统是这种规模,可以在周末时执行完全备份。备份的排程范例如下:
 
周一 差异数据库备份
周二  差异数据库备份
周三 差异数据库备份
周四 差异数据库备份
周五 差异数据库备份
周六 差异数据库备份
周日 完全数据库备份
每天 根据需要的交易记录文件备份
•  7-by-24环境的大规模系统 大规模的系统可能不允许在一天内完成完全备份。折衷的办法是将完全备份分到几天当中完成(在这个例子中,分到周六和周日):
 
周一 差异数据库备份
周二 差异数据库备份
周三 差异数据库备份
周四 差异数据库备份
周五 差异数据库备份
周六 完全档案群组备份
周日 完全档案群组备份
每天 根据需要的交易记录文件备份
这个信息是要为您提供如何排程备份的方法。由于每个系统和系统要求都是不同的,只有您才能决定最佳的排程备份。
________________________________________
改善备份
 
使用一些简单的技术,您就可以改善备份的效能和备份的执行。在本节中,您将学到其它增强效能以及改善备份的诀窍。
增强备份效能
 
增强备份效能是很重要的主题,这是因为备份执行的越快,在备份过程中 SQL Server 效能降低的时间越短。下面的技术将帮助您改善您的备份效能,并且在某些情况下也能帮助改善还原效能。(数据库还原将在 第 33 章 中讨论。)
•   使用多个备份装置 拥有多个备份装置使得 SQL Server 能够同时执行多个备份操作。这是透过 SQL Server 将备份划分到几个装置中达成的。为了建置这一点,SQL Server 根据数据文件的数量和备份装置的数量建立了大量的执行绪。备份效能同时也透过额外的执行绪得以改善,这些额外的执行绪被用以写入数据到这些装置中。同时执行操作减少了这些操作花费的时间总量,特别是在多处理器的系统中。这项技术将同时改善备份和回复效能。
 
•   在数据库中使用多个数据文件 在数据库中使用多个小数据文件,而非一个大的数据文件,这样 SQL Server 就能够同时执行更多备份。这项技术将同时改善备份和回复效能。
 
•   使用多重LAN程序段来执行备份 透过将备份分割成多重 LAN 程序段,您可以增加备份的网络频宽。如两个 LAN 程序段提供双倍频宽,三个区段提供三倍频宽等等。
 
•   阶段(stage)备份 要改善备份的效能,您可以执行这个备份作为磁盘备份,然后将磁盘备份文件拷贝到磁带机中。这种方法可以改善效能,因为磁盘比磁带快,而且它还能在磁盘上保存最新的可用备份。但这项技术只有当备份文件仍留在磁盘上时才能改善还原的效能。
 
•   使用差异备份 差异备份可以改善每个备份的效能,但是在还原整个数据库时将花费更长的时间,您将在 第 33 章 中看到。如果无法接受备份的时间过长,那么这种方法可以为您的系统提供最佳解决方案。如果您需要还原资料的机会很少,这种风险是可以接受的。
 
其它诀窍
 
下面关于执行备份的诀窍也许可以套用到您的个人环境中:
•   离开工作储存备份 如果您在工作站之外储存备份,这样备份就能在诸如火灾或洪水的灾难中保存下来。备份数据比计算机系统本身要重要的多。
 
•   确认备份 备份不可能总是好的。磁带可能变质,特别是您一次次的重复使用同一个磁带时更是如此。透过确认备份(至少有时候),您至少可以知道磁带是好的
 
•   不要每天重复使用同一备份媒体 每天重复使用同一备份媒体,您可能无法还原几天前删除的数据。循环使用备份磁带,这样您至少可以还原过去几天的信息。
 
•   保留记录 您应该制作使备份运作以及必要时如何重建系统的档案。记住,不可能总是您自己去重建系统。
 
•   备份系统数据表 记住定期备份系统数据库,例如 master、msdb 数据库。
 
这些诀窍是用来帮助您开发您自己的备份策略。每个系统是不同的,且每人的需求是不同的。再一次说明,您必须开发适合您的策略。
本章总结
 
在本章中,您学到了 SQL Server 记录文件是如何工作的、如何使用检查点来缩短数据库还原的时间,您学到了执行 SQL Server 备份的基础知识、以及完全备份和差异备份、数据库备份和交易记录文件备份之间的差别,您还学到了如何排程和改善您的备份。在 第 33 章 中,我们将继续讨论关于数据库备份、还原和回复,您将学到如何还原数据库、以及如何规划损坏回复。




31. 管理作业自动化
SQL Server代理程序服务
作业
警示
SQL Server代理程序错误记录文件
本章总结
在 第 30 章 中我们看了几项自动化设定的选项,以及 SQL Server 2000 提供的数据库选项,这些选项帮助 DBA 减少了的调整作业。在本章中将学会使用 SQL Server 提供的辅助工具,以透过 SQLServer 代理程序服务来自动执行其它的管理作业。SQLServer 代理程序服务包括自动定期执行数据库的特定作业,以及服务器发生问题或事件时,通知 DBA 或其它特定人员。这些功能的好处使得 DBA 不需要用手动或不断监控数据库系统来决定何时执行特定作业,因此有更多时间用在更难的数据库问题上,如建立和调整索引、最佳化查询、或者为未来的成长预作计划。
自动化管理作业有三个主要工具:作业、警示、和操作员。在本章中,您将学会关于 SQLServer 代理程序服务,以及如何使用服务来建立及使用作业、警示、与操作员。您也可以找到关于 SQLServer 代理程序错误纪录,这个纪录可用来追踪 SQLServer 代理程序执行的工作。
SQLServer 代理程序服务
 
SQLServer 代理程序执行从 SQL Server 独立出来的服务,称为 SQLServer 代理程序。这个服务包含在 SQL Server 2000 之中,但是必须单独启动,手动或自动均可。 第 8 章 有关于启动 SQLServer 代理程序的方法说明。一旦启动服务,就要准备好定义所需要的作业、警示、和操作员。
________________________________________
说明
SQLServer 代理程序服务在 Microsoft SQL Server 6.5 中被称为 SQL Executive。它也可以用作复写,如 第 26 、 27 、 28 章 的说明。
________________________________________
作业
 
 作业 (Jobs)是管理任务,只要定义一次就可以执行好几次。您可以手动执行作业,或者用 SQL Server 安排在特定时间执行,也可以定期执行或是警示发生时执行( < 警示 > 稍后会作说明)。作业可以由 SQL Server 陈述式、Windows NT 或 Windows 2000 指令、可执行程序、ActiveX 指令码组成。作业也可以在您使用复写或建立数据库维护计划时自动帮您建立。一个作业可由单一步骤或很多步骤组成,而每个步骤可以是一个更复杂的呼叫组合步骤─例如呼叫预存程序。SQL Server 自动监控作业的成败﹔两种情况都可以设定警示。
作业可以在本地端服务器执行,或者您在网络上有多重服务器,可以指定一台作为主要服务器,其它的作为目标服务器。主要服务器替全部的服务器储存作业定义,并且作为作业清理处,协调一切作业活动。每个目标服务器定期与主要服务器相连,若有作业变更就更新作业清单,从主要服务器下载新作业,然后切断联机来执行新作业。当目标服务器完成作业时,它会再与主要服务器连接并报告它的结束状况。
我们来看看建立作业的一个假设情况。假设您有个数据库数据表,保存了每笔银行的交易纪录,例如存提款和转帐。每笔记录有一个 timestamp 数据行说明交易何时发生。这个数据表将不断增长并且需要定期删除数据。要从数据表中删除一列,您可以用 DELETE 陈述式写一个小的预存程序来删除两个月之前的旧数据(假设银行只要保留两个月的数据)。接着您可以建立一个作业来执行这个预存程序,例如每周日晚上执行一次。这样一来,您可以确保数据表不会无限制地增长。这不但可以保留磁盘空间,而且还能提升效能。执行查询时表格中的数据越少,SQL Server 就能越快完成查询。现在让我们来看看建立作业的细节。
________________________________________
说明
SQLServer 代理程序服务必须依序执行才能使您的作业正常运作。
________________________________________
建立作业
 
您可以用 Enterprise Manager、T-SQL 指令文件、建立作业精灵、或 SQL-Distributed Management Objects (SQL-DMO)来定义作业。因为 SQL-DMO 方法与计算机的程序编制有关,不在本书的范围之内。本章节您将学会其它三种有关建立作业的方法。
________________________________________
相关信息
关于使用 SQL-DMO 来建立作业,请参阅< 在线丛书 >并索引< SQL-DMO >。
________________________________________
使用 Enterprise Manager
 
先用 Enterprise Manager 建立作业。最常用的方法之一是执行数据库备份(这也可以如 第 30 章 所提的利用 维护计划精灵 来完成)。下面的例子是建立作业备份 MyDB 数据库。它安排备份在每晚 11:00 执行,并在 Windows NT 或 Windows 2000 应用事件纪录和输出档案中纪录备份作业的成败。跟着下面步骤建立名为 MyDB_backup_job 的作业:
1. 在 Enterprise Manager 左边的窗格中,展开一个服务器数据夹,展开 管理 数据夹,然后展开 SQL Server代理程序 数据夹。在 作业 上点选右键并在快捷菜单上选择 新增作业 。显示 新增作业属性 窗口,如图31-1所示。
 
 
图31-1 新增作业属性 窗口的 一般 页签
2. 在 一般 页签中设定下列选项:
o  名称 键入作业名称─这里是在文字方块中键入『MyDB_backup_job』。作业名称最多可以有 128 个字符。服务器上的每个作业都必须是唯一的名称,并要确定使用描述性的名字。
 
o  启用 该复选框指定作业应该启动还是停用。您可能想要先停用作业以手动测试来确保运作正常。测试后得知运作正常,就可以用这个复选框启动作业,这样作业就能如期执行。
 
o  作业类别 为这个作业选择类别-在这个例子中,我们使用预设类别 未分类(本机) 。您可以从已建立的作业类别中选择,这些作业类别是安装 SQL Server 时建立的,或者也可以建立您自己的类别(想学习如何建立新类别,请参阅本章后面 < 建立新类别 > 一节)。安装的类别有 Uncategorized (Local)、数据库维护计划、全文检索、Web 辅助程序,还有复写的 10 个类别。类别是用来归类相关作业的。例如,您可以将用来执行数据库维护的作业归于同一个类别中,或是依部门分类,如会计、销售、和市场营销。类别让您能够追踪多重作业-您就不须为了一小部份的作业而花时间搜寻所有作业清单。
 
o  拥有者 建立作业的使用者。只有 sysadmin 角色可以更改谁拥有作业或是变更其它使用者拥有的作业(SQL Server 角色将在 第 34 章 中说明)。所有 sysadmin 角色与作业拥有者都可以改变作业的定义,也可以启动或停止作业。在 拥有者 下拉式选单中,选择将执行作业的使用者。本例中,作业拥有者和建立作业者是同一人,所以拥有者会自动选择正确的设定,而您可以让这个设定自行运作。
 
o  描述 在该文字方块中,必须确认一个作业要执行什么任务以及作业的目的。您应该提供描述,描述让其它使用者很快决定作业的功能。描述最多可有512个位。
 
o  目标为本机服务器 如果点选这个选项,作业将只在本机服务器上执行。如果有远程服务器连接到这个服务器上的话,就可以使用 目标为多重服务器 的选项。点选这个选项来指定远程服务器上也要执行这个作业。
 
完整的样本作业 一般 页签显示如图31-2所示。

 
 
图31-2 填入一般页签
3. 点选 步骤 页签,再点选 新增 ,就会显示 新增作业步骤 对话框,如图31-3所示。 作业步骤(Job steps) 是定义作业任务的指令或陈述式。每个作业必须至少有一个作业步骤,也可以有多重步骤。在 新增作业步骤 中的 一般 页签对话框中输入下列信息:
o 在 步骤名称 字方块中键入步骤名称-在这个例子中是输入『MyDB_backup』。
 
o 从 型别 下拉式选单中,选取一种步骤类型来执行。在这个例子中, 因为要用 T-SQL 指令来执行作业,所以选取 Transact-SQL 指令码(TSQL) 。其它选项为 ActiveX Script、操作系统命令、复写散发者、复写交易记录读取程序、复写合并、复写队列读取器、和复写快照。
 
o 从 数据库 下拉式选单中选择要执行作业的数据库名称。在这个例子中,选择 MyDB 数据库。
 
o 在 命令 文字方块中键入将作为一部份作业步骤的指令,在这个例子中,指令是 T-SQL 指令,用来将 MyDB 数据库备份到一个叫做 MyDB_backup1 的备份装置上。(这个备份装置必须事先建立好, 第 32 章 中有建立备份装置的详细说明。还有,这个简单的例子中,数据库备份每晚会被写入同一个档案中。实际上,您应该如 第 30 章 所言使用数据库维护计划来执行备份,就像它会让您每天建立新的备份装置一样。)如果有一个准备好的指令文件,您想要用它作为作业,也可以点选 开启旧档 来开启档案。
 
4. 点选 剖析 ,检查 T-SQL 步骤的语法,然后点选 进阶 页签并设定选项,如图31-4所示。在这个页签中,您可以选择作业成功或失败后执行的动作:结束作业回报成功、结束作业回报失败、或是跳到下一个步骤。您也可以指定作业没有成功时应该重试的次数,以及两次重试的间隔时间。 如果这个作业包含 T-SQL 指令或是指令码,您可以选择一个输出档,里面将有 T-SQL 的输出报告。您也可以在每次作业执行时,将输出附加在这个档案后,或是每次都覆写输出档案。点选 检视 来检视输出档案的内容。选取 将输出附加至步骤历程记录中 复选框让作业输出附加在作业历程记录表项目中。您也可以指定执行 T-SQL 的使用者。
 
 
图31-3 填写后的「新增作业步骤」对话框「一般」页签

 
 
图31-4 「新增作业步骤」对话框中填写后的「进阶」页签
5. 在已有的步骤前插入一个需要执行的新步骤,选取需要插入新步骤的现有步骤,然后点选 插入 显示 新增作业步骤 对话框,输入您要插入的步骤信息。要删除步骤,选取步骤后点选 删除 ;要编辑步骤,选取步骤后点选 编辑 。您也可以移动清单中的步骤,选取步骤后点选 移动步骤 右边的上下箭头。 起始步骤 下拉式选单允许您选择作业中哪个步骤要先执行。要先执行的步骤 ID 号码旁会出现一个绿色的标记。点选 套用 将步骤应用在作业中。如果在多重步骤之间有任何流程逻辑会导致一个步骤无法执行的话,SQL Serve 会在您点选 套用 时显示警示讯息,并且允许您修改流程逻辑。
6. 要为一个作业建立排程,点选 排程 页签。要找出服务器的目前时间,就要在 注意:目标服务器目前日期时间 下拉式选单中选取服务器名称。现在点选 新的排程 来显示 新增作业排程 对话框,如图31-5所示。排程将指定何时何日该执行作业,可在某一时刻执行也可以定期执行。如果您想在任意时刻用手动执行作业,那就不需要作业排程-您可以在想要执行作业时执行。填入排程名称 MyDB_backup_schedule,并在 排程类型 区域中设定选项(在这里要选择 重复执行 ),然后选取 启用 复选框,如图31-5所示。 启用 复选框在这里的功能和它在 新增作业属性 窗口中的功能一样。
7. 由于我们选择重复排程类型,您必须设定作业要在何时何日执行。要这样做的话,就点选 变更 显示 编辑重复执行作业排程 对话框。键入新时间和日期,点选 确定 回到 新的排程 对话框。(记住我们要在每晚 11 点设定一个每日备份。)
8. 在 新的排程 对话框中点选 确定 以接受您的排程,并回到 新作业属性 窗口。要删除排程,就选取排程名称并点选 删除 ;要编辑排程, 就选取排程名称并点选 编辑 。
 
 
图31-5 新的排程对话框
________________________________________
说明
您也可以替这个作业建立新警示。本章稍后将提到警示的更多细节。
________________________________________
9. 点选 告知讯息 页签,如图31-6所示。在这个页签上,您可以设定一个通知程序,那么操作员(或指定使用者)在作业成功、失败、或完成时会收到通知。通知可以透过电子邮件、呼叫器、或用 NET SEND 指令当成讯息透过网络传送。您可以将作业状态写入 Windows NT 或 Windows 2000 事件纪录中,甚至可以在作业成功、失败或完成后自动删除作业。若要设定操作员通知,就依需要选择 电子邮件操作员 、 传呼操作员 、和 网络传送操作员 复选框,然后在右边下拉式选单上选取操作员名称。(见本章后面 < 操作员 > 一节来学会如何建立操作员。)在最左边的下拉式选单中选取执行通知的条件。作业完成要将结果写入事件纪录或自动删除作业的时候,请选择适当的复选框,然后在相关的下拉式选单上选取执行动作的条件。在这个例子中, 要选取 写入Windows应用程序事件记录文件 复选框。
 
 
图31-6 新作业属性窗口的告知讯息页签
10. 完成设定选项后,点选 套用 来建立您的作业。然后点选 确定 退出 新作业属性 窗口回到 Enterprise Manager。
11. 在 Enterprise Manager 左边窗格中点选 作业 ,您将在右边窗格中看到含有 MyDB_backup_job 的清单。
 建立新类别 要建立新类别,请在 Enterprise Manager 左边窗格中开启一个服务器,展开 管理 数据夹,在 作业 上点选右键,在快捷菜单上点选 所有工作 , 接着选择 管理作业类别 。 作业类别 对话框出现,如图31-7所示。您可以在这里加入一个类别,检视现有类别和在类别中的作业,并可删除类别。
使用 T-SQL
 
T-SQL 命令可用来建立作业、增加步骤、并建立作业排程,这些命令分别是系统预存程序 sp_add_job、sp_add_jobstep 和 sp_add_jobschedule。这些预存程序有多个选择性参数,如下面的程序代码所示。SQL Server 对每个未指定的参数会分配一个默认值。用 Enterprise Manager 建立作业比较简单,因为它的图形化使用者接口会引导您设定作业选项,避免您漏掉一些参数。使用 T-SQL 您必须包含所有选择性参数的值,或确定任何您忽略的预设参数值能够满足作业需要。您应该用 Enterprise Manager 代替用手动来执行预存程序。您可以产生 T-SQL 指令文件,让 Enterprise Manager 用指令文件建立作业,在作业名称上点选右键,在快捷菜单中选取 所有工作 ,接着选择 产生SQL指令码 。如果需要的话,这个技术允许您用指令文件重新建立作业。

 
 
图31-7 作业类别对话框
要执行刚才所提的预存程序,您必须使用 msdb 数据库,因为这是储存程序的地方。如果要使用这些程序,要先看看预存程序中哪些参数是可用的。本章中所有的预存程序都使用同样的一般语法。预存程序 sp_add_job 的语法如下:
sp_add_job [ @job_name = ] 'job_name'
[ , [ @enabled = ] enabled ]
[ , [ @description = ] 'description' ]
[ , [ @start_step_id = ] step_id ]
[ , [ @category_name = ] 'category' ]
[ , [ @category_id = ] category_id ]
[ , [ @owner_login_name = ] 'login' ]
[ , [ @notify_level_eventlog = ] eventlog_level ]
[ , [ @notify_level_email = ] email_level ]
[ , [ @notify_level_netsend = ] netsend_level ]
[ , [ @notify_level_page = ] page_level ]
[ , [ @notify_email_operator_name = ] 'email_name' ]
[ , [ @notify_netsend_operator_name = ] 'netsend_name' ]
[ , [ @notify_page_operator_name = ] 'page_name' ]
[ , [ @delete_level = ] delete_level ]
[ , [ @originating_server = ] 'server_name' ]
[ , [ @job_id = ] job_id OUTPUT ]
sp_add_jobstep 的语法如下:
sp_add_jobstep [ @job_id = ] job_id | [ @job_name = ] 'job_name'
[ , [ @step_id = ] step_id ]
{ , [ @step_name = ] 'step_name' }
[ , [ @subsystem = ] 'subsystem' ]
[ , [ @command = ] 'command' ]
[ , [ @additional_parameters = ] 'parameters' ]
[ , [ @cmdexec_success_code = ] code ]
[ , [ @on_success_action = ] success_action ]
[ , [ @on_success_step_id = ] success_step_id ]
[ , [ @on_fail_action = ] fail_action ]
[ , [ @on_fail_step_id = ] fail_step_id ]
[ , [ @server = ] 'server' ]
[ , [ @database_name = ] 'database' ]
[ , [ @database_user_name = ] 'user' ]
[ , [ @retry_attempts = ] retry_attempts ]
[ , [ @retry_interval = ] retry_interval ]
[ , [ @os_run_priority = ] run_priority ]
[ , [ @output_file_name = ] 'file_name' ]
[ , [ @flags = ] flags ]
sp_add_jobschedule 的语法如下:
sp_add_jobschedule [ @job_id = ] job_id,| [ @job_name = ] 'job_name',
[ @name = ] 'name'
[ , [ @enabled = ] enabled ]
[ , [ @freq_type = ] freq_type ]
[ , [ @freq_interval = ] freq_interval ]
[ , [ @freq_subday_type = ] freq_subday_type ]
[ , [ @freq_subday_interval = ] freq_subday_interval ]
[ , [ @freq_relative_interval = ] freq_relative_interval ]
[ , [ @freq_recurrence_factor = ] freq_recurrence_factor ]
[ , [ @active_start_date = ] active_start_date ]
[ , [ @active_end_date = ] active_end_date ]
[ , [ @active_start_time = ] active_start_time ]
[ , [ @active_end_time = ] active_end_time ]
________________________________________
相关信息
有关每个参数和它的默认值说明,请参阅< 在线丛书 >索引中相关的预存程序名称。
________________________________________
________________________________________
说明
这里所提的预存程序,就像其它与建立和管理作业相关的预存程序一样,操作员、通知和警示都存在 msdb 数据库中。您必须使用这个数据库来执行预存程序。
________________________________________
使用建立作业精灵
 
Enterprise Manager 提供了一个精灵,这个精灵会一步一步引导您进行作业建立过程,唯一的限制是它限制您只能建立单一步骤的作业。然而,它允许您提供一个作业排程,并指定被通知作业状态的操作员。建立作业后,您可以用 Enterprise Manager 修改作业,增加更多作业步骤。
依下列步骤,用 建立作业精灵 来建立作业:
1. 从 Enterprise Manager 的 工具 下拉式选单中选择 精灵 ,在 选择精灵 对话框中打开 管理 数据夹,并选取 建立作业精灵 ,显示 建立作业精灵 欢迎画面,如图31-8所示。
2. 点选 下一步 显示 选择作业命令类型 画面,如图31-9所示。这个画面可以指定您要建立作业的步骤类型。在这个例子中,要选取 Transact-SQL 命令 。
 
 
图31-8 「建立作业精灵」欢迎画面

 
 
图31-9 「选择作业命令类型」画面
3. 点选 下一步 ,显示 输入Transact-SQL陈述式 画面(图31-10)。您必须选择执行指令的数据库,然后为作业键入陈述式,或者按一下 开启旧档 来寻找或开启含有 T-SQL 命令的档案。按一下 剖析 ,检查您输入的 T-SQl 陈述式的语法。如果您已经选择 操作系统Shell命令 或者 Active Script 作为指令类型,您就必须为这些类型输入指令。例如,键入 T-SQL 指令备份 master 数据库到事先建立的 backup_master_dev 装置,如图31-10所示。
 
 
图31-10  输入 Transact-SQL 陈述式画面
4. 按一下 下一步 ,显示 指定作业排程 画面,如图31-11所示。您可以在这里指定何时执行作业。
 现在 选项指定作业将在精灵完成作业时执行。其它的选项一看便知。在这个例子中,选取 重复执行 ,然后选择 排程 来设定排程。出现 编辑重复执行作业排程 对话框,如图31-12所示。使用这些选项建立需要的数据库,并按一下 确定 接受设定,回到 指定作业排程 画面。

 
 
图31-11 指定作业排程画面

 
 
图31-12 「编辑重复执行作业排程」对话框
5. 按一下 下一步 ,显示 作业通知 画面,如图31-13所示。在 网络传送 或 电子邮件 下拉式选单上选取通知作业完成状态的操作员。您必须已经为显示在清单上的作业定义好操作员。(图31-13显示未定义操作员。)如果要通知尚未定义的操作员,就请完成这个精灵然后新增一个操作员(本章后面 < 操作员 > 一节会说明)。接着可以更改通知操作员的作业属性。您也可以取消精灵、建立操作员、然后重新启动精灵。
 
 
图31-13 「作业通知」画面
6. 按一下 下一步 ,显示 完成建立作业精灵 画面,如图31-14所示。在这里的 作业名称 文字方块中为作业分配一个名称来取代默认值。在本例中,我们的作业命名为 Backup_master_job。检查 描述 方块中的内容,确定显示出您要的选项,并按一下 完成 来建立作业。如果您要的选项没出现,按一下 上一步 做些修正。如果作业成功建立起来的话,将会出现一个消息框。按一下 确定 关闭这个消息框。
完成 建立作业精灵 之后,Enterprise Manager 的 作业 数据夹将出现新作业。

 
 
图31-14 完成建立作业精灵画面
管理作业
 
您可以透过 Enterprise Manager 或使用 T-SQL 来管理或编辑作业。对您来说Enterprise Manager 可能比较容易使用,因为您不必担心 T-SQL 预存程序的语法和默认值,而且 Enterprise Manager 的 GUI 会引导您设定作业属性。
使用 Enterprise Manager
 
您可以用 Enterprise Manager 以手动方式为作业启动、停止、停用、启用、编辑、以及建立T-SQL程序代码。这些任务的每个用法说明如下:
•  要开始作业,在Enterprise Manager右边窗格的作业名称上按一下右键,并在快捷菜单中选择 启动作业 。
 
•  要停止正在执行的作业,并删除设定好的重试步骤,在作业名称上按一下右键,并在快捷菜单中选择 停止作业 。
 
•  停用作业,让作业在不允许执行的排程时间内可以测试。在作业名称上按一下右键,并从快捷菜单中选取 停用作业 。选择 启用作业 可以再度启用作业。
 
•  要编辑作业、排程、或其它的作业属性,在作业名称上按一下右键,并从快捷菜单中选取 内容 ,显示作业的 属性 窗口,窗口中包含了用来建立作业的4个相同页签。做好修改之后,按一下 套用 ,然后按 确定 。
 
•  如果要在不重新输入陈述式的情况下随时重建作业,就要替作业建立一个T-SQL 指令码,在作业名称上按一下右键,在快捷菜单中选取 所有工作 ,然后选择 产生SQL指令码 ,显示 产生SQL指令码 对话框。键入文件名称,选择档案格式(Unicode、ANSI 或者 OEM 文字),按一下 确定 。
 
使用 T-SQL
 
您也可以用下面的 T-SQL 预存程序来开始、停止、启动、停用和编辑一个作业。执行这些程序时,记得使用 msdb 数据库。
•  sp_start_job 立即开始指定的作业。这个程序需要作业名称或是作业 ID编号。
 
•  sp_stop_job 停止正在执行的作业。这个程序需要作业名称、作业 ID、或者主机服务器名称。
 
•  sp_update_job 允许您启用、停用、并改变作业的属性。这个程序需要作业名称或是作业 ID编号。
 
________________________________________
相关信息
要检视这些可以一起使用的预存程序和选项的语法,请参阅< 在线丛书 >并索引「指定预存程序」。
________________________________________
检视作业历程记录
 
SQL Server 在 msdb 系统数据库的 sysjobhistory 数据表中维护作业执行信息的历程纪录。您可以用 Enterprise Manager 或 T-SQL 来检视作业历程记录信息。
使用 Enterprise Manager
 
跟着下面步骤用 Enterprise Manager 来检视作业历程记录:
1. 在 Enterprise Manager 右边窗格的作业名称上点选右键,从快捷菜单上 选取 检视作业历程记录 ,显示 作业历程记录 对话框,如图31-15所示。在这里您将看到一行描述每个作业执行的信息、操作员的通知、以及在SQLServer 上接收到的错误或讯息。
 
 
图31-15 作业历程记录对话框
2. 要检视作业执行状态的其它细节,请在对话框的右上角选择 显示步骤详细信息 复选框。图31-16显示 MyDB 备份的细节。
 
 
图31-16 显示在 作业历程记录 对话框中的详细步骤
3. 要清除所有讯息,请点选 全部清除 。要更新画面来检视作业状态(开启 作业历程记录 对话框后所执行的新作业),请点选 重新整理 。要关闭 作业历程记录 对话框,请点选 关闭 。
使用 T-SQL
 
使用 T-SQL 检视关于作业排程的作业历程记录信息,在 msdb 数据库执行预存程序 sp_help_jobhistory。语法如下:
sp_help_jobhistory [ [ @job_id = ] job_id ]
[ , [ @job_name = ] 'job_name' ]
[ , [ @step_id = ] step_id ]
[ , [ @sql_message_id = ] sql_message_id ]
[ , [ @sql_severity = ] sql_severity ]
[ , [ @start_run_date = ] start_run_date ]
[ , [ @end_run_date = ] end_run_date ]
[ , [ @start_run_time = ] start_run_time ]
[ , [ @end_run_time = ] end_run_time ]
[ , [ @minimum_run_duration = ] minimum_run_duration ]
[ , [ @run_status = ] run_status ]
[ , [ @minimum_retries = ] minimum_retries ]
[ , [ @oldest_first = ] oldest_first ]
[ , [ @server = ] 'server' ]
[ , [ @mode = ] 'mode' ]
如果您没有用参数或是没有使用 job id 或 job name 参数来执行程序的话,关于所有作业排程的信息将被退回。mode 参数指定是否要退回所有历史信息(FULL)或是退回一个摘要(SUMMARY)。默认值设定为 SUMMARY。
________________________________________
相关信息
关于预存程序其它选项的细节,请查阅< 在线丛书 >并索引 sp_help_jobhistory。
________________________________________
警示
 
 警示 (alert)是发生在服务器上,对于事件或是执行状况的一个响应动作。警示可以通知操作员,使得指定的作业能够执行,并将事件转交到另一个服务器上。 事件 (event)是一个错误或讯息,它被写入 Windows NT 或 Windows 2000 应用程序事件记录中(您可以用 Windows NT 或 Windows 2000 Event Viewer 来检视)。 效能条件 (performance condition)是系统效能的特色,可以用 Windows NT 效能监视器或 Windows 2000 系统监视器来监视,如 CPU 公用程序或被 SQL Server 使用的多个锁定。在本章中,我们将着重在 Windows 2000 的系统监视器上,纵使 Windows NT 效能监视器的用法也很相近。
事件发生时,SQLServer 代理程序将比较事件与您所定义的警示清单,如果警示已被事件所定义的话,那警示就会启动。当所定义的效能门坎达到系统监视器中指定的 SQL Server 对象,就会引发效能条件的警示,就像在系统监视器对象 General Statistics 之下的计数器 User Connections。例如,您可以设定当计数器的值达到 50 时发生警示。( 第 36 章 中有系统监视器的说明。)
________________________________________
说明
为了让您的警示能够运作,必须执行 SQLServer 代理程序服务。
________________________________________
事件讯息纪录
 
在说明如何为事件建立警示之前,我们先回顾一下让讯息传送到 Windows NT或 Windows 2000 应用程序事件记录的事件类型;只有这些事件可以用来设定警示。事件(或错误)重要层级从 19 到 25 是自动回报到 Windows NT 或 Windows 2000 应用程序事件记录中的,因此可以启动警示。默认值中事件重要层级少于 19 的都没有纪录,所以警示就不能用这些事件启动。要使那些事件能够记录并且可以启动的话,您必须使用 sp_altermessage、RAISERROR WITH LOG 陈述式,或者 xp_logevent 来改变事件或讯息的纪录状态。本节中,您将学到如何建立使用者定义的事件讯息,并学会如何发出警示讯息以确保事件将写入应用程序事件记录中。
________________________________________
说明
当 SQL Server 讯息纪录在 Windows NT 或 Windows 2000 应用程序事件记录时,它同时也记录在 SQL Server 记录中了。要在 Enterprise Manager 中检视 SQL Server 记录,请展开 管理 数据夹,然后展开 SQL Server记录文件 数据夹。
________________________________________
建立使用者定义事件讯息
 
系统所有的信息和使用者定义讯息都储存在 master 数据库的 sysmessages 数据表中。要建立使用者定义讯息,请用 T-SQL 系统 sp_addmessage 预存程序,语法如下:
sp_addmessage [ @msgnum = ] msg_id ,
[ @severity = ] severity ,
[ @msgtext = ] 'msg'
[ , [ @lang = ] 'language' ]
[ , [ @with_log = ] 'with_log' ]
[ , [ @replace = ] 'replace' ]
使用者定义讯息必须有一个讯息 ID 值(msg_id)为 50001 或者更大的值。Severity 参数是错误的重要层级,范围从 1 到 25,越高的数字表示越高错误的重要层级。只有系统管理员可以将重要层级设定成 19 到 25。msg_text 参数是错误讯息的内容,当错误发生时会显示在应用程序事件记录中。language 参数指定讯息使用哪种语言写入,因为 SQL Server 可以安装多种语言。with_log 参数可设定成 TRUE 或 FALSE,指定讯息是否要记录在 Windows NT 或 Windows 2000 应用程序事件记录中。默认值为 FALSE,这样在使用 RAISERROR WITH LOG(在下一节说明)时会覆写这个设定值。Replace 参数指定新讯息应该取代现存有相同讯息 ID 编号的讯息。
Public 角色成员可允许执行 sp_addmessage,但是要建立讯息重要层级为 18 以上或将 with_log 设定成 TRUE 的话,您就必须是 sysadmin 角色成员之一。
我们来看看一个使用 sp_addmessage 的例子。下面的陈述式建立一个记录在事件记录当中的新讯息(因为 with_log 被设定成 TRUE):
sp_addmessage 50001, 16,"Customer ID is out of range.", @with_log="TRUE"
GO
事件讯息的警示记录设定
 
假设一个现有的讯息或是您刚建立的讯息不允许记录(或者您没有包含 with_log 参数),就像下面的例子:
sp_addmessage 50001, 16,"Customer ID is out of range.", @with_log="TRUE"
GO
如果您稍后要记录讯息的话,就必须改变讯息的纪录状态。这样的话,请使用sp_altermessage 设定记录,如下面的例子:
sp_altermessage 50001, WITH_LOG, "TRUE"
GO
另一种方法,您可以在 WITH LOG 选项中使用 RAISERROR 叙述,将讯息回传到应用程序,并回传到应用程序事件记录以及 SQL Server 记录中。例如,下面叙述用重要层级为 16、状态值为 1 来传送讯息 50001,状态(state)是当错误发生在编码中不止一个地方的时候,用来追踪的数字:
RAISERROR (50001, 16, 1) WITH LOG
GO
________________________________________
相关信息
有关使用 RAISERROR 的更多细节,请参阅< 在线丛书 >索引中的RAISERROR,在 找到的主题 对话框中选择 使用 RAISERROR 。
________________________________________
要改变讯息的记录状态,您可以使用在 master 数据库中的延伸预存程序xp_logevent。使用这个程序时,讯息将被传送到事件记录和 SQL Server 记录中,但不会传送到客户端的应用程序中。下面是使用这个程序的例子:
USE master
GO
xp_logevent 50002, "Customer ID is out of range.", warning
GO
要有前两个参数,并且必须含有使用者定义讯息 ID 编号(一定要大于 50000)和出现在输出纪录的消息正文。第三个参数-重要层级-是选择性的,可以是 informational、warning 或 error 三个字符串之一。重要层级的设定决定了在 Event Viewer 中,讯息之后要出现什么类型的图像,这样才能够很快地识别出警告或者错误。在 Windows 2000 中,信息的讯息有一个蓝色的 i 图像,警告讯息有一个黄色的 ! 图像,而错误讯息有一个红色的 X 图像。如果没有指定重要层级,默认值为 informational。
建立警示
 
现在我们准备在事件和效能条件上建立警示。要建立警示,您可以使用 Enterprise Manager、T-SQL 或 SQL-DMO。我们将只说明 Enterprise Manager 和 T-SQL 方法,因为 SQL-DMO 超出本书范围。
使用 Enterprise Manager 建立事件警示
 
在这个例子中,我们将在重要层级为 24 的系统讯息上建立一个警示。讯息在事件记录中以默认值纪录,使用者不需要介入变更它的记录状态。请跟着下面步骤建立事件警示:
1. 在 Enterprise Manager 的左边窗格中展开一个服务器数据夹,展开 管理 数据夹,展开 SQL Server代理程序 数据夹。在 警示 上按一下右键,并在快捷菜单上选取 新增警示 ,出现 新增警示属性 窗口,如图31-17所示。在 一般 页签上键入警示的名称(可输入128个字符)。在这个例子中键入『IO_error_alert』。 启用 复选框允许您启用或停用这个警示。停用警示将导致它不被引发,就像停用作业一样。本例中,要确定警示可启用。在 型别 下拉式选单中选择 SQL Server事件警示 ,因为我们要建立警示,而这个警示在某个事件发生时会被解除。(另一种警示类型选项是S QL Server 效能条件警示,这种警示类型的例子将在下一节说明。)我们的例子是要建立当 I/O 错误发生时会解除的警示。
 
 
图31-17 「新增警示属性」窗口的「一般」页签
2. 在 新增警示属性 窗口的 事件警示定义 区域中,选择 错误号码 或 重要性 指定您要启动警示的事件,然后指定一个错误编号或是重要层级。如果重要层级指定好了,那个重要层级的所有错误都将引发警示。在本例中,要选取 错误号码 ,然后点选 ... 按钮来寻找编号。出现 管理SQL Server讯息 对话框,如图31-18所示。
3. 要搜寻指定的错误,请在 搜寻 页签中的 重要性 清单上选取一个类别,然后按一下 寻找 。找到的错误讯息将列在 讯息 页签上。 搜寻 页签的底部有两个复选框,可以用来限制搜寻。 只包含记录的讯息 复选框可以让搜寻来检索自动记录在事件记录中的讯息。 只包含使用者自订的讯息 复选框限制只能搜寻使用者定义的讯息。例如,要寻找所有严重的硬件错误,要选取在 重要性 清单方块中的 024-严重错误 : 硬件错误 ,然后按一下Find。错误编号823(重要层级为24)将出现在 讯息 页签上,如图31-19所示。
 
 
图31-18 「管理SQL Server讯息」对话框的「搜寻」页签

 
 
图31-19 「管理SQL Server讯息」对话框的「讯息」页签
4. 按一下 确定 接受这个讯息,并回到 新增警示属性 窗口的 一般 页签。 数据库名称 下拉式选单让您指定只有当事件来自选取的数据库中,警示才会引发。保持 所有数据库 的默认值设定。 错误讯息中所含的文字 文字方块允许您键入字符串(可到 100 个位),来限制将引发警示的错误,而这些错误文字将显示那些刚键入的字符串。如果让这个文字方块空着的话,就不会受到任何限制。
5. 按一下 回应 页签,如图31-20所示。这个页签中,您可以指定警示发生时应该采取什么行动。选取 执行作业 复选框,在下拉式选单上选取一个作业名称,让作业可以在警示发生时执行。按一下 新增操作员 ,建立一个新操作员来通知。现有的操作员会出现在 通知操作员 清单上。您可以指定操作员是否应该用电子邮件、呼叫器、网络传送、或是综合上述方法来通知。
 
 
图31-20 「新增警示属性」窗口的「响应」页签
如果指定用电子邮件通知操作员,而且也选取了 将警示的错误文字包含于 复选框,错误文字将在警示讯息中传送给操作员。在电子邮件中将附加的文字键入到页签底部的 待传送的其它告知讯息 文字方块。附加文字最多可有 512 位。图31-20显示操作员 TestOperator,选择用电子邮件通知。附加的讯息包含在内。注意 响应间隔延迟 文字方块。这些文字方块设定指定警示重复发生时,操作员将多久被通知一次。设定 60 分钟表示操作员每 60 分钟被通知一次。
6. 要接受您输入的的警示和响应,请按一下 套用 。然后点选 确定 来关闭窗口。
使用 Enterprise Manager 建立效能条件警示
 
当某种效能条件发生时,我们可使用 Enterprise Manager 建立效能条件警示。注意,SQLServer 代理程序每 20 分钟轮询一次效能计数器,所以如果在轮询之间有几秒钟的高低情况发生,是监测不到的。跟着下面步骤建立警示:
1. 在 Enterprise Manager 的左边窗格中展开一个服务器数据夹,展开 管理 数据夹,展开 SQL Server代理程序 数据夹。在 警示 上按一下右键,并在快捷菜单上选取 新增警示 ,出现 新增警示属性 窗口(图31-21)。在 一般 页签的 名称 文字方块中为警示键入一个名称(本例中使用的名称是user_alert)。指定一个效能条件警示,选取 型别 下拉式选单中的 SQL Server效能条件警示 。
2. 在 效能条件警示定义 区域,定义一个将启动警示的效能条件。选取您要使用的 SQL Server 效能对象,作为 对象 下拉式选单中的启动对象,然后选取要在 计数器 下拉式选单中使用的计数器。设定 发出警示的时机为计数器达 选项,指定在哪种情况下警示会被引发。最后设定一个门坎,如果超过这个特定值,就会引发警示。图31-21显示当 SQL Server User Connections 计数器到达100时,这个设定就会引发警示。
3. 要完成警示的设定,就在 回应 页签上设定选项,如前面步骤5所述。 按一下 套用 然后按 确定 。
 
 
图31-21 「新增警示属性」窗口的「一般」页签
使用 T-SQL 建立事件警示或效能条件警示
 
您也可以使用 T-SQL 来建立警示,但是要记得如果用 Enterprise Manager 建立警示,您可以为那些警示产生 T-SQL 指令码。(要这样做的话,请在 SQL Server代理程序 数据夹中的 警示 上按一下右键,在快捷菜单上点选 所有工作 ,然后选择 产生SQL指令码 。)您可能会发现用 Enterprise Manager 建立警示比较容易,因为 T-SQL 方法需要学习并记住很多选项参数以及它们的默认值。
要用 T-SQL 增加警示,请使用 sp_add_alert 预存程序。不管要建立事件警示或是效能条件警示,都要使用这个程序。参数选项决定警示要建立成何种类型。sp_add_alert 的语法如下:
sp_add_alert [ @name = ] 'name'
[ , [ @message_id = ] message_id ]
[ , [ @severity = ] severity ]
[ , [ @enabled = ] enabled ]
[ , [ @delay_between_responses = ] delay_between_responses ]
[ , [ @notification_message = ] 'notification_message' ]
[ , [ @include_event_description_in = ] include_event_description_in ]
[ , [ @database_name = ] 'database' ]
[ , [ @event_description_keyword = ] 'event_description_keyword_pattern']
[ , { [ @job_id = ] job_id | [ @job_name = ] 'job_name' } ]
[ , [ @raise_snmp_trap = ] raise_snmp_trap ]
[ , [ @performance_condition = ] 'performance_condition' ]
[ , [ @category_name = ] 'category' ]
预存程序用来修改警示、检视警示信息,并分别删除 sp_update_alert、sp_help_alert 和 sp_delete_alert 的警示。记住,所有的预存程序都可在 msdb 数据库中找到。
________________________________________
相关信息
关于本节所提的程序细节,请参阅< 在线丛书 >并索引 < 预存程序 >。
________________________________________
操作员
 
 操作员 (operators)是可以在作业完成或警示发生时,从 SQL Server 接收通知的个人。操作员是一个人,负责维护执行 SQL Server 的系统。您已经学会如何定义传送给操作员的通知讯息。正如前面所提,用来与操作员联系的方法有三种:传送电子邮件讯息、呼叫、和使用网络传送指令(传送网络讯息到操作员的计算机中)。系统必须符合好几个必要条件才能才能让这些方法顺利运作。使用电子邮件和呼叫联系的话,必须在服务器上安装 MAPI-1-compliant e-mail client(MAPI表示 Messaging API),如 Outlook 或是 Exchange Client,而且必须为 SQLServer 代理程序建立一个邮件档案夹。使用呼叫,还需要在邮件服务器上安装三方的 e-mail-to-pager 软件来处理内部的电子邮件讯息,并且将讯息转换成呼叫讯息。使用网络传送,必须以 Windows NT 或 Windows 2000 为操作系统-网络传送不支持 Windows 95/98。
________________________________________
相关信息
关于如何设立邮件数据夹,请参阅您的 email 用户软件文件。有关 pager-to-e-mail 软件的详细信息,请参阅您的呼叫服务提供员或呼叫文件数据。
________________________________________
在 SQL Server 上必须定义每个操作员。您可以建立不只一个操作员来分担责任,在联络不上其它操作员时,就通知故障安全防护操作员(例如在呼叫失败时)。您可以使用 Enterprise Manager、T-SQL 和 SQL-DMO 来建立操作员。本节将说明 Enterprise Manager 和 T-SQL 的方法,SQL-DMO 则不在本书讨论范围之内。
使用 Enterprise Manager 建立操作员
 
跟着下列步骤用 Enterprise Manager 建立操作员:
1. 在 Enterprise Manager 的左边窗格中展开一个服务器数据夹,展开 管理 数据夹,展开 SQL Server代理程序 数据夹。在 操作员 上按一下右键,并从快捷菜单上选取 新增操作员 ,显示 新增操作员属性 窗口,如图31-22所示。在 一般 页签中为新操作员键入名称,然后输入一个或多个:操作员的电子邮件名称、呼叫器的电子邮件名称、以及网络传送地址。
如果输入呼叫地址,您可以指定在 传呼待命排程 区域中何时可以呼叫操作员。例如,如果有不只一位操作员,您可以分配责任,让一个操作员在星期一、三、五、和星期日被呼叫,而另一个操作员在星期二、四、和星期六被呼叫。
2. 按一下 告知讯息 页签。如果点选 警示 (在标页签的右上角),会显示存在的警示清单,如图31-23所示。在字段中选择复选框,您可以指定何种警示将通知操作员,以及将用何种联络方法通知操作员。
 
 
图31-22 「新增操作员属性」窗口的「一般」页签

 
 
图31-23 「新增操作员属性」窗口的「一般」页签出现「警示」
3. 建立新操作员时,您将无法点选 作业 ,因为没有作业要通知新的操作员,而且新的操作员也还不存在。要避免新的操作员接收通知,请清除 操作员已准备接收告知讯息 复选框。停用这个选项使您暂停传送通知给操作员-例如,在操作员度假时。然后当操作员回来时,您可以撤销复选框再启用通知。
4. 按一下 传送电子邮件 按钮,建立列在 一般 页签上用来传给操作员的文字讯息。(如果没有输入电子邮件地址的话,将出现错误。)您可以传送电子邮件,描述为操作员建立的通知类型。在 告知讯息 页签底部,将看到关于最近键入、用来通知操作员的信息。
使用 T-SQL 建立操作员
 
T-SQL 指令用来建立操作员、修改操作员信息、检视操作员信息、以及删除操作员。在 msdb 数据库中系统的预存程序分别有:sp_add_operator、sp_update_operator、sp_help_operator 和 sp_delete_operator。您可能会再度觉得使用 Enterprise Manager 是比较容易的方法。用 Enterprise Manager 建立操作员后,可以产生 TSQL 指令码。
这里是 sp_add_operator 的语法:
sp_add_operator [ @name = ] 'name'
[ , [ @enabled = ] enabled ]
[ , [ @email_address = ] 'email_address' ]
[ , [ @pager_address = ] 'pager_address' ]
[ , [ @weekday_pager_start_time = ] weekday_pager_start_time ]
[ , [ @weekday_pager_end_time = ] weekday_pager_end_time ]
[ , [ @saturday_pager_start_time = ] saturday_pager_start_time ]
[ , [ @saturday_pager_end_time = ] saturday_pager_end_time ]
[ , [ @sunday_pager_start_time = ] sunday_pager_start_time ]
[ , [ @sunday_pager_end_time = ] sunday_pager_end_time ]
[ , [ @pager_days = ] pager_days ]
[ , [ @netsend_address = ] 'netsend_address' ]
[ , [ @category_name = ] 'category' ]
________________________________________
相关信息
列在本节中关于预存程序选项的细节,请参阅< 在线丛书 >索引中 < 预存程序 >的部分。
________________________________________
SQLServer 代理程序错误记录文件
 
SQLServer 代理程序服务本身拥有错误记录,记录了 SQLServer 代理程序的启动与关闭,以及任何跟S QLServer 代理程序作业或警示相关的警告、错误和通知讯息。要使用 SQLServer 代理程序错误记录文件,请跟着这些步骤进行:
1. 在 Enterprise Manager 的左边窗格中展开一个服务器数据夹,展开 管理 数据夹,展开 SQL Server代理程序 数据夹上按一下右键,并从快捷菜单上选取 显示错误记录文件 ,出现错误记录,如图31-24所示。
2.  型别 下拉式选单让您检视错误讯息、警告讯息、信息讯息或者全部的讯息(所有类型)。图31-25显示在开启 SQLServer 代理程序之后,错误讯息看起来像什么。(注意, 所有类型 是在 型别 下拉式选单中选取的。)
 
 
图31-24 「SQL Server代理程序错误记录」对话框

 
 
图31-25 「SQL Server代理程序错误记录」对话框,显示所有讯息的类型
3. 每次开启 SQLServer 代理程序时,错误讯息将重新启动,覆写记录中的现有讯息。您可以搜寻含有特定字符串的讯息,只要在 内含的文字 文字方块中键入字符串,然后按Enter或者点选 套用筛选条件 。图31-26显示搜寻字符串 CPU 之后的错误记录。
 
 
图31-26 错误纪录讯息中搜寻字符串的结果
4. 在讯息上按两下,检视 SQL Server 代理程序 Error Log Message 对话框,如图31-27所示。
 
 
图31-27 「SQL Server代理程序错误纪录讯息」对话框
如果搜寻结果不止一种讯息,您可以用 上一步 和 下一步 按钮来转换讯息。如果只找到一个讯息,这些按钮将无法使用。
如果操作员因为某种原因或是作业无法执行而联络不上的话,SQLServer 代理程序错误纪录将收到一个错误讯息。您应该偶尔检查这个错误记录,确定是否发生任何错误需要处理。
本章总结
 
在本章中,您学会了如何使用 SQLServer 代理程序服务,透过定义作业和操作员、设定通知给操作员、以及建立事件警示和效能条件警示来使管理工作自动化。您学会了在建立事件警示时,错误重要层级的重要性,以及如何变更错误讯息的记录状态,以便在 Windows NT 或 Windows 2000 应用程序事件记录中启用纪录。您还学会了如何检视 SQLServer 代理程序错误记录文件,档案中记录了关于 SQLServer 代理程序的信息,以及发生在警示与作业中的错误和警告。在 第 32 章 中,我们将讨论备份 SQL Server 数据库。




30. Microsoft SQL服务器管理
SQL Server自动设定功能
数据库维护计划
本章总结
使用适当的设定,并在数据库中执行例行的维护任务,是让服务器最佳化的关键。本章中将学到 SQL Server 2000 中关于动态设定的特别功能,这些功能可简化设定数据库的程序。同时我们也将使用数据库维护精灵(Database Maintenance Plan Wizard)制作数据库的系统自动维护计划,使数据库保持在最佳状态。
SQL Server 自动设定功能
 
SQL Server 内含自动化的功能,用于减少与设定和调节关系型数据库管理系统(RDBMS)有关的负荷。由于这些功能是从 SQL Server 7.0 发展出来的,SQL Server 7.0 的使用者对这些功能应该不陌生。本章我们会学习这些功能的运作、如何利用它们降低数据库的工作量,以及在必要时消除自动化的功能设定。
动态内存管理
 
 动态内存管理 (dynamic memory management)可让 SQL Server 依据系统的规模分配内存大小,以便动态的管理缓冲快取区和程序快取区。由于 SQL Server 具动态内存管理功能,DBA 就不必手动控制快取区的大小。但在某些情况下,可能需要限制 SQL Server 所能使用的内存大小。
动态内存管理的运作
 
动态内存管理以不断监视系统中可用物理内存的大小以达到管理的功能。SQL Server 依需要以及可使用内存的量,决定增加或减少 SQL Server 内存共享区(将在下个部分说明)。当内存大小还算固定时,这个功能就很实用;但是当内存被用于处理系统中 SQL Server 以外的其它程序时,就会因为 SQL Server 不断改变内存的配置而产生问题。
如果一台计算机的系统主要就是用来作为 SQL Server 数据库服务器,就很适合使用动态内存管理。在这类系统中,在 SQL Server 处理范围之外的动作,所用到的内存大小较固定,因此 SQL Server 会不断的自动配置内存,使工作有效率地进行,这样的配置会一直持续到没有再多的物理内存可供配置。如果现有的处理程序不需要更多的内存,系统就会一直保持这样的状态。若另一个程序又需要用到内存,SQL Server 就会解除新程序所需的内存大小,并配置让新的程序顺利使用。
用来处理作业程序的计算机系统就不适合使用动态内存。由于内存的需求不断改变,处理程序就必需时常增减内存。在这样的系统下,内存的用量经常改变,SQL Server 就必须不断地设定和撤销内存的配置,增加系统的负担,也使处理过程缺乏效率。如果能在 SQL Server 中以手动方式配置固定的内存大小,或是预设 SQL Server 可配置的最大与最小的内存容量,可使这类系统运作得更好,稍后在本章会有更详细的说明。
不论使用的是动态或是手动来管理内存,系统运作的好坏要看内存的运用是否能发挥最大的效果。透过监视 SQL Server 的内存配置,可以确定内存的使用量是否固定的变更,或者一直保持在稳定的状态。使用 Windows 2000 的效能监视器(Performance Monitor)可以监视内存,如 SQL Server 中的 Total Server Memory(KB效能计数器)。内存管理员(Memory Manager)对象会显示 SQL Server 最近消耗的内存大小(KB)。
内存共享区
 
SQL Server 动态地配置和撤销集区中的内存。内存共享区由下列组件的内存组成:
•   缓冲快取区 保留数据库中已被内存读取的数据页面,缓冲快取区通常占用了大部分的内存共享区。
 
•   连接内存 用在每个 SQL Server 的连接点。连接内存由可以持续追踪每个使用者内容的数据结构所组成,包含了光标位置信息、查询参数值、以及预存程序信息。
 
•   数据结构 含有关于锁定和数据库描述的全域信息,包括有关锁定拥有者、被锁定的类型、和各种不同的档案及档案群的信息。
 
•   纪录快取区 用来保存被写在交易纪录中的交易信息,也用在读取当前写入纪录快取区的纪录信息。纪录快取区提升了纪录写入的效能,和缓冲快取区是不同的。
 
•   程序快取区 用来储存 Transact-SQL 陈述式的执行计划,并储存程序执行时的所有步骤。
 
因为内存配置是动态的,如果可以以动态内存管理,内存共享区会不断地增加或减少,而且内存共享区的五个区域也可以动态地改变各自的大小。这个功能是由 SQL Server 控制的。举例来说,若内存的需求较多,就会有较多的 T-SQL 陈述式被储存在程序快取区中,SQL Server 就会从缓冲快取区拿走一些内存给程序快取区使用。
使用附加内存
 
SQL Server 可以存取的内存大小要看 Windows 操作系统的使用量。Windows NT Server 4 支持 4GB 的内存,其中 2GB 用在使用者程序上,另外的 2GB 留给系统使用。这表示在 NT 4 中,SQL Server 可配置的内存限量在 2GB 之内。但是在 Windows NT Server 4 企业版中,每个程序处理所配置的虚拟内存空间比原先大了 50%(3GB)。可以做这样的扩充是因为系统本身的配置减少到 1GB。用在程序处理的虚拟内存增加,因此可以将内存共享区的大小扩充到将近 3GB。要使用这个 Windows NT 4 企业版中的支持,您必须在 Boot.ini 的档案启动数据行中加入 / 3GB的标记,这可以透过控制台的系统图标来完成。
对于 Windows 2000 操作系统的两个版本,SQL Server 2000 企业版都可以用Windows 2000 Address Windowing Extensions(AWE)API 来提供更大的内存空间。在 Windows 2000 高阶服务器版中支持将近 8GB,而在 Windows 2000 Datacenter Server 中支持将近 64GB 的内存。AWE 只支持这两种操作系统,无法支持 Windows 2000 专业版。(详见本书 第二章 和< 在线丛书 >中的「在Windows 2000中使用AWE内存」。)
内存设定选项
 
下面 SQL Server 组态设定和内存配置有关。可以透过 SQL Server Enterprise Manager 或者 sp_configure 预存程序来设定组态。若要使用 sp_configure 来检视这些组态,必须将 show advanced options 的选项设定成 1。
•  awe enabled 让 SQL Server 使用扩充内存(之前提过的 AWE 内存)。这选项只能在 SQL Server 企业版中使用,而且只能用 sp_configure 来设定。
 
•  index create memory 限制在索引建立过程中排序的内存大小。index create memory 选项是自设的,大部分情况下它不需要调整。但是如果建立索引时遇到困难,可能要试着在默认值上增加选项的值。
 
•  max server memory 设定 SQL Server 可以分配给内存共享区的最大内存空间。如果 SQL Server 要动态地配置和撤销内存,就留下默认值设定;如果要静态地配置内存(因此使用空间不变),可将这个选项和 min server memory 设定成相同的值。
 
•  min memory per query 指定分配给执行查询的最小内存空间(KB)。
 
•  min server memory 设定 SQL Server 可以分配给内存共享区的最小内存空间,留下默认值给动态内存配置。如果要静态地分配内存,可将这个选项设成和 max server memory 相同的值。
 
•  set working set size 指定 SQL Server 分配的内存不能交换,即使其它程序可以更有效地使用内存。当 SQL Server 可以动态配置内存时,不应该使用 set working set size 选项。它应该只用于 min server memory 和 max server memory 设成相同数值时。这样一来,SQL Server 将分配无法变更的静态内存大小。
 
________________________________________
说明
要发挥 AWE 的内存选项的优势,必须将 SQL Server 2000 企业版与 Windows 2000 高阶服务器版或 Windows 2000 数据中心服务器版一起执行。
________________________________________
其它动态设定选项
 
有些动态设定选项并不属于服务器内存,在 SQL Server 中也可使用。若保留这些选项的默认值,SQL Server 将动态地设定所有选项。默认值可以覆写,虽然这并非必要,但您仍应该知道使用手动设定时这些选项如何运作。
使用 SQL Server Enterprise Manager 或 sp_configure 来设定选项(并不是所有的选项都可以透过 Enterprise Manager 来设定)。用 sp_configure 设定选项,在命令提示窗口中开启 Query Analyzer或 osql 联机,用参数执行预存程序如下:
sp_configure "option name", value
参数 option name 就是设定选项的名称,而 value 就是要设定的数值。如果执行命令时没有包含参数值,SQL Server 会回传给指定选项当前的值。要看所有选项的清单和它们的值,直接执行 sp_configure,不需任何参数。有些选项被视为进阶选项。为了用 sp_configure 来检视和设定这些选项,您必须先将 show advanced options 设定为1,语法如下:
sp_configure "show advanced options", 1
透过 Enterprise Manager 设定的选项不受 show advanced options 的影响。
在 Enterprise Manager 中,选择服务器后按下鼠标右钮,在快捷菜单中选择 内容 进入 SQL Server属性(组态) 窗口,如图30-1所示。

 
 
图30-1 Enterprise Manager 中属性窗口的一般页签
在窗口的页签可存取某些动态选项。接下来的章节中将描述 SQL 和内存无关的动态选项,并说明这些选项是否可在 Enterprise Manager 上设定,以及在哪里找到这些选项。
锁定选项
 
SQL Server 根据当前的需求来动态地设定系统中使用锁定的数量大小。您可以设定可用数量的最大值,限制 SQL Server 用在锁定上的内存数量。预设设定为 0,这允许 SQL Server 根据系统需求,动态地要求分配和撤销锁定。SQL Server 允许内存最高有 40% 用在锁定上。保持 locks 参数为默认值 0,并允许 SQL Server 根据需要分配锁定。这个选项是进阶选项,并且只能用 sp_configure 设定。
复原间隔选项
 
复原间隔表示 SQL Server 回复数据库所需要的每数据库最大分钟数。(请参阅本章中 < 自动检查点 > 一节。)SQL Server 回复数据库需要的时间要看最后一次的检查点何时发生。因此复原间隔(recovery interval)的值是 SQL Server 用来动态地决定何时执行自动检查点。
举例来说,每次 SQL Server 关闭时,检查点会在所有数据库中执行,因此当SQL Server 再度启动,只需一点点时间复原。但如果 SQL Server 被强制停止(由于电源中断或其它失误),SQL Server 要再启动时,它将退回那些没有提交的交易来回复数据库,进行那些已经提交但在 SQL Server 停机时还没写入到磁盘中的交易。如果在特定的数据库中最后检查点正好在系统失误前执行的话,数据库的回复时间较短;如果最后检查点在系统失误之前很久的时间执行的话,回复时间较长。
SQL Server 根据内建路径和复原间隔的设定来决定多久执行一次检查点。例如,如果将复原间隔设定为 5,SQL Server将 在每个数据库执行检查点, 这样数据库在失误后的回复时间约需五分钟。复原间隔的默认值为 0,表明由 SQL Server 自动设定。使用默认值时,回复时间少于1分钟,而且检查点几乎每分钟执行一次。很多情况下,检查点频繁执行会造成的效能降低。因此,大部分的时候您应该增加复原间隔的值来减少检查点的数量。您选择的值将视企业需求而定,看使用者在系统失误之后可以等多久。一般说来,设定 5~15 的值就行了(表示回复时间为 5~15 分钟)。
复原间隔选项是进阶选项。可以在 Enterprise Manager 中的属性窗口设定。点选 数据库设定 页签,如图30-2所示。在 复原间隔(分钟) 方块中输入一个值。

 
 
图30-2 设定回复时间
使用者连接选项
 
SQL Server 动态设定使用者连接数,最多允许 32767 个使用者连结。透过设定联机使用者选项,您可以指定允许进入 SQL Server 的最大值(允许的使用者连接数也受限于应用程序和硬件)。使用者连接仍可动态地设定成最大值。
举例来说,如果只有 10 个使用者登入,就分配 10 个使用者连接对象。如果达到最大值,而 SQL Server 还需要更多使用者连接的话,就会出现一个错误讯息,告知您使用者连接已达最大值。
大部分的情况中,不需要改变联机使用者选项的默认值。注意每个连接约需要40KB 的内存。
可以使用 SQL Server Query Analyzer,和下列的 T-SQL 陈述式来确定您的系统允许的使用者连接最大值:
SELECT @@MAX_CONNECTIONS
联机使用者选项是进阶选项,可以在 Enterprise Manager 中设定。只要点选服务器属性窗口中的 联机 页签,并在 使用者同时联机最大值 微调方块中输入一个数值,如图30-3所示。

 
 
图30-3 设定使用者连结
开启对象选项
 
 开启对象 (open objects)选项是进阶选项,只能用 sp_configure 设定,指定可同时开启的最大数据库对象个数,如数据表、检视表、预存程序、触发程序、规则和默认值,都可以在同时间启动。默认值 0 表示系统允许 SQL Server 动态地调整开启对象的数量。建议保留默认值设定。如果您做了改变,而 SQL Server 需要比设定还多的开放对象,就会收到错误讯息,告知超过系统允许的开放对象数量。还有,每个开放对象会消耗一些内存,所以系统需要更多物理内存来支持开放对象的数量。
统计
 
系统需要数据列统计来增加查询效能。SQL Server 能搜集数据表数据列中和数值分布有关的统计信息。Query Optimizer 利用这个信息决定查询的最佳执行方法。统计可以在两种数据列中取得:索引的一部分和不在索引中而在查询的述词中使用。留下 SQL Server 设定的数据库默认值,可使 SQL Server 自动建立两种型式的统计。索引栏数据和索引同时建立,非索引栏数据则在需要查询时建立(只有单一数据列而非多重数据列,如同稍后在 < 建立统计 > 这节所说明的一样)。一旦统计旧了(一段时间没有使用),SQL Server 会自动将它们去除。
建立非索引数据列和索引数据列时,SQL Server 只用了数据表中的数据样本,而非每一资料行都用。这减少了作业的过度需求,但在某些情况下,样本并不能正确地显示数据的特征,统计将不完全精确。
在 Enterprise Manager 中,可以设定或取消数据库自动建立统计的功能。首先开启所选定的数据库属性窗口,点选 选项 页签,就会看见 自动产生统计资料 的复选框。(图30-4显示范例distributions数据库的复选框)。这个选项由默认值挑选。

 
 
图30-4 distribution 数据库的属性窗口
在数据库的属性窗口,也会看到 自动更新统计数据 的选项。这个选项说明SQL Server 在必要时将自动更新数据表数据列的统计。当数据表中大部分的数值改变时,这些统计就必须更新(透过更新、插入、或删除操作)。当多数资料改变,当前的统计就比较不精确。SQL Server 将自动决定何时应该更新统计。如果您选择撤除这个选项以建立统计的能力,您就必须使用手动执行任务,以确保数据库运作得宜。以下章节会告诉您如何手动建立与更新统计。
建立统计
 
您可以在数据表的特定数据列中,使用 T-SQL 指令 CREATE STATISTICS 来手动建立统计。手动建立统计和自动建立不同。手动可让您结合多重资料列的统计,产生如 复制值 和 相异值 的平均数。CREATE STATISTICS 的语法如下:
CREATE STATISTICS stats_name ON
   table_name ( column [ , column... ] )
   [ [WITH [ FULLSCAN | SAMPLE SIZE PERCENT ]
   [ , NORECOMPUTE ]
您必须提供您要建立的统计名称、数据表名称、和至少一个数据列名称。可以指定多重数据列名称来搜集组合数据列的统计,但不能指定计算资料行或者 ntext、 text、or image 数据型别作为统计数据列。不管是完全扫描或个别取样都可以用作统计搜集。因为要扫瞄每数据行数据表,完全扫描花费的时间比个别取样久,但它会比较精确。如果您使用个别取样,您必须指定样本数据的百分比。NORECOMPUTE 指定撤销统计的自动更新能力,让统计不再代表数据能否使用。
您也许要在数据列中建立统计,一起用在查询的述词中。举例来说,您可以在Northwind 数据库 Employees 数据表的 FirstName 和 LastName 数据列中建立统计,用员工的姓氏和名字来搜寻员工数据。T-SQL 程序代码的用法如下:
CREATE STATISTICS name
ON Northwind..Employees (FirstName, LastName)
WITH FULLSCAN, NORECOMPUTE
这个陈述式计算 FirstName 和 LastName 数据列中所有数据行的统计,并撤销统计的自动验算功能。
如果数据库的所有数据表和所有数据列都用手动建立统计,却不想一栏一栏键入CREATE STATISTICS 陈述式的话,可用 sp_createstats 预存程序。预存程序将在下个部分说明。
sp_createstats
 
您可以经由预存程序 sp_createstats,在使用者数据表中所有合适的数据列建立统计。尚未有统计的资料列都将建立统计。每组统计只会在一个单一资料列中。sp_createstats 的语法如下:
sp_createstats [ 'indexonly' ] [ , 'fullscan' ]
   [ , 'norecompute' ]
indexonly 参数限定唯有索引内的数据列可以建立统计。fullscan 参数限定每一数据行都将执行完全扫瞄,而非随机取样。norecompute 参数限定不能在新的统计上自动更新统计。新的统计都以原先建立的资料列名称命名。
更新统计
 
SQL Server 用默认值自动更新统计。您可以使用 UPDATE STATISTICS 命令来撤销这个选项,改用手动更新统计。这个指令允许更新索引栏和非索引栏的统计。您也许要建立一个 UPDATE STATISTIC 的指令码,然后定期执行指令码,就像 SQL Server 的工作。这将有助于维持最新的统计,并且确保较好的查询效能。(见 第17章< 重建索引 > ,有更多关于语法和 UPDATE STATISTICS 选项的细节。)要设定或撤除特定统计的自动更新状态,可用 sp_autostats 预存程序,说明如下:
sp_autostats
 
利用系统的预存程序 sp_autostats,可以设定或撤除特定统计的自动更新。执行程序不会造成统计更新;更确切地说,它决定该不该出现自动更新。预存程序要和一个两个或三个参数一起呼叫:数据表名称、选择性标记和统计名称。标记说明自动更新的状态,并设定成 ON 或OFF。在数据表中显示目前所有统计的更新状态(索引栏和非索引栏统计),用指定的数据表名称执行指令。下面指令显示 Customers 数据表的统计状态:
USE Northwind
GO
sp_autostats Customers
GO
输出显示每个统计的名称,不论自动更新设定在 ON 或OFF,或是最近的更新在何时。不要被输出的第一数据列上 Index Name 标题困扰。它表示所有统计,不是只有索引而已。如果您不需手动关掉这些统计的更新,它们会显示 ON 的状态, 就像 SQL Server 的默认值。
要撤除 Northwind 数据库 Customers 数据表中所有统计的自动更新,必须使用下列指令:
USE Northwind
GO
sp_autostats Customers, 'OFF'
GO
您可以将标记值设成 ON 让自动统计更新再度运作。改变特定统计的状态或者索引的统计数据,包括个别的统计名称或索引名称。例如下列指令能设定 PK_Customers 索引的自动统计更新:
USE Nnorthwind
GO
sp_autostats Customers, 'ON', 'PK_Customers'
GO
Customers 数据表中所有其它统计的状态将不改变。
档案成长
 
使用 SQL Server 2000 时,您可以设定数据文件依需要自动增长。这个功能很好用,因为它防止您不小心用完空间。然而不能因为这个功能就不监控数据库大小,或是偶尔才执行一下容量规划。您应该经常注意数据表的增长有多快。然后才能决定是否要定期删除不必要的档案(也许是一些数据表中的过期数据)。这么一来,就能减缓资料表的增长。随着数据表中数据数量的增加,查询会花更多时间,效能层级就下降。建立数据库时,设定自动档案增长的标题(如 第九章 所提),您将学会如何变更现有数据库的增长选项。自动档案增长选项可在 Enterprise Manager 中设定。 跟着下面的步骤执行:
1. 在 Enterprise Manager 左边的窗格中,展开一个服务器,选择 数据库 数据夹。在想要修改的数据库上按下鼠标右钮(以修改 MyDB 数据库为例),在快捷菜单中选择 内容 进入数据库的属性窗口。
2. 点选 数据文件 页签(如图30-5所示),看看数据库数据文件的属性。在 档案属性 中的选项是用来控制数据文件的成长方式。要让档案自动增长,勾选 自动成长 复选框。如果让档案自动成长,应该设限让档案不会无限制地增长。
 
 
图30-5 MyDB 属性窗口的数据文件页签
使用 档案大小上限 中的选项指定档案可成长的上限。点选 限制档案成长 并在微调方块中键入最大值。如果点选 不限制档案成长 ,您会发现磁盘驱动器子系统一不小心就装满数据,造成效能和操作问题。
使用档案增长区中的选项可以限定档案增长的速度。如果点选 以MB表示 ,一旦数据文件满了,SQL Server 会依指定数值增加大小。如果点选 以百分比表示 ,SQL Server 将依照目前大小的百分率来增加资料文件大小。
3. 点选 交易记录文件 页签(如图30-6所示),设定交易记录的自动增长选项。这些选项的使用方法跟 数据文件 页签相同,在这里也应该为交易记录档案设限,档案才不会无限制成长。
 
 
图30-6 MyDB 数据库属性窗口的交易记录文件页签
自动档案增长功能在很多情况都很方便,只要确定您没有让档案意外地消耗掉系统所有的磁盘空间。
检查点
 
SQL Server 自动执行检查点操作。检查点的频率会依指定的 SQL Server 设定选项中复原间隔的数值自动计算。这个选项指定系统失效事件发生时,您所要等待的数据库回复时间(分钟)。检查点出现频率必须足以确保系统回复时间少于指定的分钟数。当 SQL Server 在 SHUTDOWN 陈述式或服务控制管理员中关闭时,检查点也会自动出现。您也可以用 CHECKPOINT 陈述式手动设立检查点。
如果想要系统执行最佳化,而且又能允许很长的回复时间的话,可以将复原间隔设成很大的值,例如 60。这代表要是系统失效,要花 60 分钟才能完成自动回复。检查点出现造成大量磁盘写入,它们会从使用者交易中取走处理资源,因而减慢使用者的响应时间。这就是执行较少的检查点经常可以协助改善所有交易效能的原因。当然,这个值设太高,系统一失效的话,就会导致过长的停机时间。一般的复原间隔设定介于 5 到 15 分钟之间。
复原间隔的默认值为 0。这个设定允许 SQL Server 依据系统负载来决定执行检查点的最佳时间。一般说来,使用默认值时,检查点约每分钟执行一次。如果您注意到检查点经常出现,可能就要调整复原间隔设定。要确定 SQL Server 是否过度执行检查点的话,就用 SQL Server 追踪标记-T3502。这个标记使得检查点信息被写在 SQL Server 错误记录中。注意检查点会出现在每个数据库中。
数据库维护计划
 
维护计划是一组任务,SQL Server 会自动在数据库根据您指定的时间表执行。 维护计划的目的在自动操作重要的管理任务,这样工作就不会被忽略,并能减少 DBA 的手动工作量。您可以替每个数据库建立个别的计划,为单一数据库建立多重计划,或是为多重数据库建立单一计划。
建立维护计划时,您可以排定的四个主要管理任务类型是:
•  最佳化
 
•  完整性检查
 
•  完整数据库备份
 
•  交易纪录备份
 
执行这些任务对于维持良好效能和可回复的数据库是很重要的。您的计划所要包括的最佳化任务类型,取决于您的数据库效能和使用率。执行完整性检查是用来确保健全且一致的数据库的好方法。还要有定期备份,以确保在系统失效或使用者错误的情况下,能够回复数据库。由于这些备份是如此的重要,您应该设立自动备份策略。我们稍后将在这个章节看到每个任务类型的更多细节。
用 Database Maintenance Plan Wizard 建立一个维护计划。本章节中,您将学会如何使用这个精灵,如何在维护计划中显示工作和如何编辑计划。
使用 Database Maintenance Plan Wizard 建立维护计划
 
依下列步骤执行数据库维护计划精灵:
1. 用以下任一方式可启动 数据库维护计划精灵 :
o 在 工具 菜单中选择 数据库维护计划 。
 
o 在左边窗格中点选一个数据库名称,并在右边窗格中的 维护 标题下点选 新增维护计划 。如果没看到 维护 标题,检查是否在 检视 菜单中选择了 工作清单 。也许要向下卷动屏幕才看得到。
 
o 点选一个数据库名称,在 工具 菜单中选择 精灵 ,展开 选择精灵 。
 
对话框中的 管理 数据夹,然后选取 数据库维护计划精灵 。
o 展开左边窗格中的服务器,展开 管理 数据夹,在 数据库维护计划 上按下鼠标右钮,从快捷菜单中选择 新增维护计划 。
 
o 在数据库名称上按下鼠标右钮并选择 所有工作 ,从快捷菜单上选取 维护计划 。
 
一旦你开启精灵,你将会看到欢迎画面,如图30-7。

 
 
图30-7 「数据库维护计划精灵」的欢迎画面
2. 选择 下一步 进入 选取数据库 画面,如图30-8所示。选择需要建立维护计划的一个或多个数据库。
3. 选择 下一步 进入 更新数据最佳化信息 画面,如图30-9所示。可为刚刚建立的数据库选择最佳化类型:
o  重新组织数据及索引页 这个选项用特定的填满因子(或者每页的可用空间数)来改善更新的效能,除去或再造数据库中所有数据表的索引。只读数据表就不需要这个页面。对于经常插入或更新的数据表来说,索引页中最初的可用空间会开始填满,页面也开始拆分。选择这个选项可以重建索引,替未来的档案增长重新建立可用空间,避免页面拆分时造成的延迟和数据占用。
 

 
 
图30-8 选择数据库画面
您可以选择根据可用空间的原始大小来重建索引,或者您可以指定一个新的保持空白页面比率。如果您设定的比率太高,就必须冒着数据读取效能降低的风险。如果您选择这个选项,就不能选下一个 Update Statistics Used By Query Optimizer 选项。
________________________________________
提示
移除与重建索引会比用 DBCC DBREINDEX 花时间, 正如 第17章< 重建索引 > 所讨论的一样。您也许会想建立自己的工作来重建索引,而不使用这个选项。
________________________________________

 
 
图30-9 更新数据最佳化信息画面
o  更新查询最佳化所使用的统计数据 选择这个选项可使SQL Server 重新取样数据库中所有索引的分布统计。它用这个信息来选择查询的最佳执行计划。如果不必为了更新统计而改变预设选项(本章前面曾说明过),SQL Server 会自动产生统计,用相对应于每个索引的数据表中数据较小的比率来采样。
 
这个选项可用来强制 SQL Server 执行另一个采样,使用较大比率的指定数据,或者决定多久 SQL Server 应该更新统计,而不是任由它决定。越大比率的资料采样,统计就越精确,但 SQL Server 也要花更多时间来产生统计。当索引栏中的数据被大量修改时,这个信息有助于改善效能。您可以用 SQL Server Query Analyzer 检验查询的执行计划,确定索引是否有效地使用,确定是否有必要选择这个选项。如果选了这个选项,就不能选之前 Reorganize Data And Index Pages 的选项。
o  从数据库档案中移除尚未使用的空间 这个选项可用来移除未使用的空间;这个过程也就是我们所知的档案收缩(file shrink)。可以指定应该有多大的未用空间才进行压缩,以及压缩之后要有多少比率的空间应该保留。一旦移除了可用空间,您可以用 DBCC SHRINKFILE 来缩减档案大小,如果需要的话,还能让它比刚建立时还小。这让之前被档案占用的磁盘空间可用于其它需要的地方。还有,移除未使用空间的压缩资料可以提高效能。在只读数据表中,压缩是不必要的。
 
可以选择 变更 按钮进入 编辑重复执行作业排程 ,指定任务的执行时间,如图30-10所示。这些任务可以在系统使用率较低执行(如周末或晚上),因为它们需要花较多时间完成,可能会延迟响应使用者的时间。
4. 选择 下一步 进入 数据库完整性检查 画面,如图30-11所示。这个画面中,可以选择是否要执行完整性检查。完整性检查会执行 DBCC CHECKDB 指令来检验数据表和索引的配置与结构完整性(如果选择索引选项)。您可以选择检查中是否包括索引、SQL Server 是否应该修复发现的小问题(建议选择这个选项)、以及是否应该在备份之前执行所有的完整性检查。 如果选择在备份前执行检查,并在检查时发现问题,那么将不执行备份。点选 Change 来改变这些任务的执行时间。完整性检查可能花好几个小时执行, 这取决于您的数据库大小。因此要确定将它们安排在数据库使用率较低时执行。检查应该定期执行,也许每周或每月一次,或是在数据库备份前进行。
 
 
图30-10 编辑重复执行作业排程对话框

 
 
图30-11 数据库完整性检查画面
5. 选择 下一步 进入 指定数据库备份计划 画面,如图30-12所示。这个画面可以选择是否要建立自动备份计划(建议使用这个计划)。勾选 将数据库备份视为维护计划的一部份 ,即可以建立自动备份( 第32章 有关于备份的详细说明)。您可以指示 SQL Server 在完成时检验备份的完整性。SQL Server 会确定备份完成,而且所有的备份内容都能存取。您也可以指示备份是否要先储存在磁带或磁盘上。点选 Change 来改变备份的执行时间。
6. 选择 下一步 进入 指定备份磁盘目录 画面,如图30-13所示。只有当您在上个画面中指定备份到磁盘上,才会出现这个画面。如果指定备份到磁带,画面就不会出现。这里可以指定备份文件的位置,也可以使用预设的备份目录。如果所要备份的不只一个数据库(如 master、model、msdb),就将每个数据库备份放在它所属的子目录下,让备份档系统化。可以选择自动删除某段时间的备份文件来挪出磁盘空间,并可以指定备份文件的扩展名。
 
 
图30-12 指定数据库备份计划画面

 
 
图30-13 指定备份磁盘目录画面
7. 选择 下一步 进入 指定交易记录文件备份计划 ,如图 30-14 所示。这个画面和图 30-12 的 指定数据库备份计划 画面类似,不过这个画面的选项是用来建立备份交易纪录。交易纪录备份应该在数据库备份之间执行。要回复从上次数据库备份至今的任何变更,可以用交易纪录备份。换句话说,交易纪录备份让您回复数据库备份之间的数据。
 
 
图30-14 指定交易记录文件备份计划画面
如果您选择在磁盘上储存备份,下一个会看到的画面是 指定交易记录文件备份磁盘目录 ,在这个画面中可以提供备份文件位置信息。
8. 选择 下一步 进入 产生报告 画面,如图 30-15 所示。这个画面提供您建立报告的选项,包含维护计划任务执行的结果。在这个画面中,您也可以选择储存报告的位置、删除超过某日期的报告,并可以用电子邮件传送这份报告到指定的地址。
9. 选择 下一步 进入 维护计划历程记录 画面(图30-16)。这里可以选择维护历史报告是否要写入本机服务器的数据库数据表中,还可以设定报告的最大容量。您也可以将报告写入远程服务器并指定报告的最大容量。
 
 
图30-15 产生报告画面

 
 
图30-16 维护计划历程记录画面
10. 选择 下一步 进入 完成数据库维护精灵 画面,如图30-17所示。这个画面显示维护计划的摘要。这个计划有个预设的名称,但也可以在 计划名称 的文字方块中键入指定名称。检查摘要,如果想要改变任何选项可以回去修改。如果计划无误,就选择 完成 。
 
 
图30-17 完成数据库维护精灵画面
在维护计划中显示工作
 
维护计划范例中,我们在四个类型里各建立一个任务。要看工作列表或排程任务,就开启 Enterprise Manager 左边窗格中 管理 数据夹,展开 SQL Server代理程序 ,然后选择 作业 ,如图30-18所示。

 
 
图30-18 用维护计划建立的作业
编辑维护计划
 
要编辑维护计划,先在 Enterprise Manager 左边窗格上点选已建立的数据库名称,然后选择右边窗格中 维护 标题之下的计划名称(或许必须向下卷动才看得到标题),数据库维护计划的对话框就会出现,如图 30-19 所示。
完成数据修改后, 一般 页签允许指定哪些数据库适用于维护计划。其它的页签可改变原先 数据库维护计划精灵 中的设定。完成计划修改时点选 确定 ,维护计划就马上依照新的安排开始进行。
________________________________________
说明
您必须让 SQL Server Agent 从自动维护计划开始依进度执行。详情参见 第31章 。
________________________________________

 
 
图30-19 「数据库维护计划」对话框中的「一般」页签
本章总结
 
在这一章中,您已经学会 SQL2000 的动态设定功能,这个功能帮助您减少执行DBA 时数据库的使用量。您也学会制作数据库维护计划,可以自动执行管理任务。下一章将告诉您如何使用 SQL Agent 来定义工作和警示。透过设定工作和警示,您可以让管理任务的自动化更进一步。




29. 使用 Microsoft SQL Server 分析服务
Analysis Services概观
安装Analysis Services
使用Analysis Services
本章总结
Microsoft SQL Server 2000 Analysis Services(过去被称为 OLAP Services),是 SQL Server 2000 中设计来协助您从事 在线分析处理(online analytical processing,OLAP) 的一个组件,利用这个组件可让您在您的数据仓储与数据超市中存取与采撷资料。在本章中,您可学习到何谓 Analysis Services 组件,如何安装以及如何使用这些组件;此外,您也会学习到 SQL Server 2000 中 Analysis Service 新增的功能。由于本书主要是写给 SQL Server 管理员而非应用程序开发人员,因此我们的讨论将仅止于安装、设定与管理 Analysis Services 等主题,应用程序开发的部分则不在讨论范围之内。
________________________________________
说明
在本章中,我们可能会不断的提到 数据仓储(data warehouse) 与 资料超市(data mart) 这两个专有名词。数据仓储可以从几个不同的方向来定义,其中之一是把它视为一个商业数据的仓库,其储存了从公司 在线交易处理(online transaction processing,OLTP) 系统所获得的历史数据以及当前数据。数据超市类似于数据仓储,不过其所包含的资料仅与公司的某一方面有关。举例来说,公司可能拥有一个数据仓储,内含应付帐款、应收帐款以及人力资源等数据,以及一个数据超市,内含应付帐款资料。组成数据仓储与数据超市的数据通常被规划成星状结构描述或雪花状结构描述,这些在本章稍后都会有所说明。本章所讨论的概念大部份均能用在数据仓储与数据超市,因此除非特别说明,我们使用数据仓储来同时代表这两种数据库。
________________________________________
Analysis Services 概观
 
Analysis Services 是一套工具,可用来协助您开发与管理用于在线分析处理的数据。Analysis Services 由 Analysis Service 服务器、English Query 以及其它支持组件所组成。Analysis Service 服务器建构数据的 cube 协助您进行多维度分析,Cube一词是用来描述一个汇总或摘要的数据集合,藉以处理复杂的分析查询,如每月销售结果与销售计划。(Cube 会在本章稍后 〈OLAP Cubes〉 一节中详细说明。)
在多维度分析中,多个查询会从不同的观点或维度来搜寻数据库。举例来说,假设现有一个自行车商数据库,其中仍保持着去年的销售数据。在多维度分析作业中的一个查询可能正在搜寻客户购买习惯,另一个查询搜寻的却是每月销售量,同时更有一个查询找的是某一特定款式的自行车或组件的销售成绩。虽然数据是分享给所有的查询,但每个查询却以不同的观点(维度)来看待资料。
Analysis Service 组件
 
Analysis Services 提供了一些工具与精灵,让您可用来存取多维度资料。Analysis Service 由下列组件组成:
•   分析管理员 :提供一个 GUI 来使用 Analysis Service,如建立 Cube、管理安全性以及浏览数据来源。
 
•   资料仓储架构 :一组实作 SQL Server 2000 数据仓储功能的组件与 API。
 
•   数据转换服务(DTS) :协助加载及转换数据到数据超市或数据仓储。DTS 是由汇入精灵与汇出精灵组成,可用来迁移数据及转换数据。DTS 的细节介绍请参阅 第24章 。
 
•   储存机制(Repository) :包含一些接口、数据库结构描述模型,以及预先定义的数据转换方式以符合数据仓储架构。因为数据转换是建立在有规则的基础上,所以它们的定义可以储存起来,以供将来重新使用。
 
•   资料采撷(Data Mining) :提供了定义与实作多维度 cube 的算法。
 
•   English Query :英文语系的问题转换为可以在数据库上执行的 SQL 陈述式。
 
•   延伸标记语言(XML) :提供一个标准格式化与数据呈现的语言。XML 是应用程序对应用程序之间数据转换的重要组件,并可用来将数据出版至因特网。
 
在本章中,我们会将这些组件组合在一起,犹如组合拼图的各个部分,藉以提供一个统合的工具。
OLAP Cube
 
在 Analysis Services 中资料的主要表现形式是 OLAP cube。 Cube 是详细数据以及摘要数据的多维度表现形式, 详细数据 是特定数据列的数据,而 摘要数据 是汇总数据。Cube 是基于数据自身的分析需求而设计的。每一个 cube 代表一个不同的商务实体,如销售额、存货等等。Cube 的每一个面表示资料中不同维度的情状。换言之,cube 是由数据许多不同的面向所组成,所以称为一个「数据 cube」。
Analysis Services cube 可透过两种数据库结构描述来建立:星状结构描述和雪花结构描述。 结构描述(Schemas) 事实上是一个发展中的论题,但为了适当的描述 Analysis Services,我们在这里简单的了解一下结构描述。这两种结构描述都是由事实数据表和维度数据表构成。Analysis Services 在数据表中汇总这些数据以建立 cube。让我们更详细一点来看这个过程。
事实资料表
 
 事实数据表(fact table) 是数据仓储中储存历史数据的数据表,这些历史数据是数据仓储的核心信息。在我们的自行车商范例中,这个信息是一个发生在自行车商行的交易记录(包括数据库交易与销售交易)。这个记录内的数据涵盖了交易日期、交易类型、销售项目、交易的总金额、顾客姓名、销售员姓名等等。这个记录可用来作为多维度分析的基础。
正如您所看到的,事实数据表的数据是以商业交易为中心的数据。这些交易可以是某物品的销售、信用卡交易和利润等等。基本上,事实数据表记录着一些商业事件的类型。
数据仓储中的事实数据表是数据库中最大的数据表,并且也是操作最频繁的数据表。您可能想象得到,事实资料表可以包括数百万个记录,且能够占据超过 1TB(或 1024 GB)的空间。
维度资料表
 
 维度数据表(dimension table) 用来定义事实数据表中的字段,例如售货员姓名、交易类型或是项目等等。这个过程与 正规化(normalization) 过程相类似,两者都是拣取有用的数据以加快处理的效率。事实数据表包含交易的历史信息,而维度数据表所包含的信息,则指出如何从事实资料表中取得有用的材料。换言之,维度资料表是用来载明事实资料表中所包含的资料的意义。
举例来说,对于一个包含着销售记录的事实数据表而言,可能有一个维度数据表包含着与销售代表有关的信息,可用来建立像是每个业务员的月份销售额这类摘要资料;而另一个维度数据表则是包含着地区信息,可用来建立每地区月份销售额这类摘要数据。
维度数据表并不像事实资料表那般庞大,相反的是维度数据表通常很小且往往仅含有几个数据列。数据仓储一般说来只会有一个到两个事实资料表,但却有好几个维度资料表。
结构描述
 
 星状结构描述(star schema) 是相当常见的一种资料仓储架构,它由一个事实数据表和一些维度数据表组成。星状结构描述意味着一个事实数据表被维度数据表所环绕,呈一颗星的形状。每一个维度数据表相当于事实数据表中的一个资料行。这些维度数据表是用来架构分析的基础,以便我们对事实数据表中的数据进行分析。
 雪花结构描述(snowflake schema) 中,几个维度资料表在联结到事实数据表之前相互联结,换句话说,先建立一些维度数据表的阶层,每一层相当于事实资料表中的一个资料行。图 29-1 显示了星状结构描述与雪花结构描述。

 
 
图29-1 星状与雪花结构描述
资料汇总
 
Analysis Services 是以维度数据表内的数据为基础,从而建立事实数据表内数据行的汇总。举例来说,与员工相关的维度数据表可用来建立以员工为基础的销售数据摘要信息。与项目相关的维度数据表可用来建立以项目为基础的数据的摘要信息。因为汇总是基于维度数据表来建立数据的不同切面(也就是维度),所以可构造一个数据的虚拟 cube,如前所述。
由 Analysis Services 建立的 OLAP cube,本质上就是依照星状或雪花结构描述来进行计算的汇总函数。您使用 Analysis Services 精灵来建立这些汇总,进而利用汇总来建立商业模型,做出商业决策。
中继资料(Metadata)
 
「中继数据」是用来描述与数据相关的数据,因此,用来描述数据库数据的摘要与详细数据便被称为中继资料。以我们刚刚的例子来说,销售数据表即周围的维度数据表表现了数据的状态。我们建立的摘要信息(业务员的销售数据、各项物品的销售资料)便是中继资料。Analysis Services 的主要益处便是建立中继数据(摘要数据表或汇总)的能力,利用 Analysis Services,您可以简单地建立中继资料随后应用于各种工作,而不用很麻烦的亲手维护这些数据。
SQL Server 2000 数据分析增强功能
 
SQL Server 2000 在数据分析及数据仓储上提供了不少新增功能,这些新增或增强功能包括了一些工具与信息,能用来增进数据分析的处理。在本节中,您会学习到这些新增功能中最主要的部分。
数据采撷增强功能
 
Analysis Services 已整合了新的数据采撷技术,可用来发现关系型数据库与 OLAP cube 之间的数据关联性。这些关联性可被加入到现有的 OLAP cube 已提供额外的数据分析。其中一个独一无二的数据采撷新功能是 Microsoft Decision Tree。Microsoft Decision Tree 使用精密的分类技术与算法来分析数据,接着它会建构一或多个决策树,可用来针对新数据进行预测分析。举例来说,我们的自行车商行便可透过这项技术建构决策树来分析潜在客户的信用历史数据与交易历史数据,由此预测该客户的信用风险。
数据采撷的另一个新功能是丛集的使用。用于数据采撷的丛集技术与 第12章 中所描述的丛集类型不并相同。当 Analysis Services 执行丛集时,它会使用一种被称为最邻近法的算法将数据录分组成具有类似特性的丛集。许多时候,这些关联性都会被隐藏或不易被察觉。因此,丛集技术可以说打开了数据分析的另一扇大门。
此外,SQL Server 数据采撷组件也包含了一些新的精灵与对话框,让数据采撷变得更易于利用。这些新增功能让 DBA 在建立与维护数据超市或数据仓储时,可以更快地执行大部分相关的工作。
维度增强功能
 
SQL Seever 包含了数种新增的维度资料表。SQL Server 现在支持父子式维度、关系型 OLAP(ROLAP)维度以及可写入的维度。
父子式维度允许来源数据表中成员之间父子式连结的阶层架构定义。父子式关联性的一个例子是一个来自各部分的组件组合结构。父代为单一的部份,可以拥有许多的子组件,即子代。当进行数据分析时,可使用父子式维度来加强子组件与该部份的连系。
ROLAP 维度可用来解决 Analysis Services 使用的标准多维度 OLAP(MOLAP)模式的容量限制问题。MOLAP 模式允许维度可包含近乎 500 万个成员。一旦成员的成长超过了这个限度,就需要 ROLAP 维度。ROLAP 维度可成长得极为庞大,不过在查询成员集时 MOLAP 模式的效能却比 ROLAP 要好很多。因此,只有在维度非常庞大时才应定义为 ROLAP 模式。
当您使用可写入维度(write-enabled dimension)时,维度的成员可透过分析管理员以及支持回写的客户端应用程序来更新。可使用 SQL Server 角色来控制客户端应用程序对维度的写入存取。SQL Server 角色将在 第34章 介绍。
安全性增强功能
 
SQL Server 2000 也包含了安全性的增强功能,可针对您用于商务分析的数据提供更佳的保护,毕竟这些数据有可能相当敏感。这些新增功能包括了变更维度数据表的安全性、数据格安全功能、以及支持额外的验证技术。
维度数据表如今是在 SQL Server 的角色基础(role-based)安全性模式中进行操作。依照每一个角色的定义,您可以限制其存取个别的维度、层级及成员。此外,您也可设定这些资源的读取与读/写权限。SQL Server 2000 同时支持 FAT 及 NTFS 两种系统的角色基础安全性。
SQL Server 2000 允许您在 cube 的数据格层级实施角色。分析管理员包含了定义数据格安全性的对话框,您可以控制角色对任何 Cube 数据格组合的存取。此外,每个角色的读取与读/写权限可以不同。
由于 SQL Server 2000 包括了 Windows 2000 安全性模式,当使用者或应用程序需要存取 cube 及其数据时,SQL Server 2000 支持 Kerberos 通讯协议、NT License Manager Security Support Provider、或是其它任何使用 安全性使用者提供接口(Security Support Provider Interface,SSPI) 的提供者来执行验证动作。这让您可以在 SQL Server 安装的所有层级上均有整体一致的安全性。
English Query 增强功能
 
在 SQL Server 2000 中 English Query 的功能已经增强,可更完整的整合 Microsoft Visual Studio 6.0 等套装产品。English Query 让程序开发人员可以将英文叙述整合到应用程序中,而不是 T-SQL 陈述式。此外,新的图形化使用者接口工具也对开发 English Query 陈述式提供了相当大的帮助。SQL Server 还内含了 SQL 项目精灵,可自动地建立基础数据库结构以支持 English Query,让 English Query 环境更易于设定与使用。这个精灵会扫描数据库的数据表并建立相关的 SQL Server 组件。
安装 Analysis Services
 
Analysis Services 是 SQL Server 2000 的一个组件,要安装 Analysis Services,请遵循下列步骤:
1. 从装选单中,按一下 SQL Server 2000的组件 ,然后按一下 安装 Analysis Services ,出现欢迎画面。
2. 按 下一步 进入 软件授权合约 对话框。在您阅读并同意该授权之后,按 是 。
3. 出现 选择组件 对话框,如图 29-2。在这个对话框中,您可以选择您要安装的 Analysis Services 组件。按一下每个组件名称前的复选框以选择所有的组件。如果组件之前已经完成安装,您将无法改变它复选框的状态。要选择新的位置来安装 Analysis Services,请按 浏览 。在您选好目的数据夹后,按 下一步 。
 
 
图29-2 「选择组件」对话框
4. 出现 储存数据的数据夹位置 对话框,如图 29-3。这个对话框与 选择目的数据夹 对话框很类似,不过,此处您要选择的是储存数据的数据夹位置。您可以按 浏览 来指定一个有别于默认值的位置。在您选好数据的数据夹位置后,按 下一步 。
 
 
图29-3 「储存数据的数据夹位置」对话框
5. 出现 选择程序数据夹 对话框,如图 29-4。此处您可以选择要放置 Analysis Services 的程序数据夹(也就是开始菜单上 Analysis Services 出现的位置)。默认值一般说来都可以接受。按 下一步 完成安装。
 
 
图29-4 「选择程序数据夹」对话框
在您完成 Analysis Services 的安装后,可以安装 English Query。虽然 English Query 可以说是 Analysis Services 整体服务的一部分,不过它们的安装却是分开的。您并不一定要安装 English Query 才能使用 Analysis Services。要安装 English Query,请遵循下列步骤:
1. 从 SQL Server 2000 安装选单中,按一下 SQL Server 2000 的组件 ,然后按一下 安装 English Query 。安装程序会先安装 Microsoft Data Access Components (MDAC) 及 Microsoft Visual Studio 组件。在这些组件完成安装后,会出现欢迎画面。按 Continue 继续安装。
2. 出现 Microsoft English Query 2000 的软件授权合约对话框。在您阅读同意后,按 I Agree 。
3. 出现 Microsoft English Query 2000 Setup 对话框,如图 29-5。此处您可选择您需要的安装类型- Complete 或 Run-time Only 。 Complete 会安装所有的组件, Run-time Only 则允许您指定要安装哪些组件。您也可以指定安装的数据夹,不过预设数据夹通常可以接受。除非您是 English Query 的专家,否则按 Complete 即可。接着会安装 English Query Components 组件。按 OK 完成安装。
 
 
图29-5 「Microsoft English Query 2000 Setup」 对话框
在您完成安装后,若要使用 Analysis Services 及 English Query元 件,请按 开始 / 程序集 / Microsoft SQL Server / Analysis Services 。在 Analysis Services 的子目录中,您有下列 3 个选项:
•   分析管理员 :启用 Analysis Services 的主要组件。这个组件包括了一些精灵与公用程序,可让您开始 Analysis Services 服务。
 
•   在线丛书 :启用 Analysis Services 在线文件。
 
•   MDX Sample Application :启用 Analysis Services 提供的一个应用程序范例。
 
使用 Analysis Services
 
现在我们已介绍了 Analysis Services 及其安装的程序,接着让我们来看一下如何使用它所提供的服务来建立并管理您的数据仓储。在本节中,我们要先设定一个数据来源,接着在该数据来源上建立一个 OLAP 数据库,最后在数据库上建立一个 cube。
设定数据来源
 
要将 Analysis Services 连接至 SQL Server 数据库,首要步骤是为服务器设定一个 ODBC 系统数据来源。您可以利用 系统管理工具 中的 ODBD 数据来源 公用程序来完成这个工作。要设定系统数据来源,遵循下列步骤:
1. 按 开始 / 程序集 / 系统管理工具 / 数据来源(ODBC) ,出现 ODBC 数据来源管理员 对话框,如图 29-6。
 
 
图29-6 「ODBC 数据来源管理员」对话框
2. 按一下 系统数据来源名称 卷标,如图 29-7,您会发现在 系统数据来源 方块中列出了一些已有的数据来源清单。这些数据来源中有些已定义为联机至 SQL Server。依数据库使用方式的不同,有时我们会需要多个 ODBC 数据来源参照同一个数据库,这当然是允许的。在本例中,我们要建立一个参照 Northwind 数据库的 ODBC 数据来源。
 
 
图29-7 「ODBC 数据来源管理员」的「系统数据来源名称」卷标
3. 按一下 新增 ,出现 建立新数据来源 对话框,如图 29-8。在选单方块中,选择 SQL Server ,然后按 完成 。
 
 
图29-8 「建立新数据来源」对话框
4. 出现 建立新的数据来源至 SQL Server 对话框,如图 29-9。此处您必须给定数据来源的名称,并给予说明,且须指定要联机的 SQL Server。按 下一步 继续。
 
 
图29-9 「建立新的数据来源至 SQL Server」对话框
5. 接下来的对话框如图 29-10,您可指定当使用者联机至 SQL Server 时要采用的验证模式。您可选择 以网络登入识别码进行 Windows NT 认证 或是 以登入识别码及由使用者输入密码进行 SQL Server 认证 。(使用者验证模式在 第34章 中介绍。)在对话框下方,您会看到一个预设为选取的复选框。如果您不需要在此时联机至 SQL Server 以获得其它选项的预设设定,将复选框改为不选取的状态。按 下一步 继续。
 
 
图29-10 指定验证模式
6. 接下来的对话框如图 29-11,您可指定要使用的数据库、数据库名称及 ANSI 模式。Analysis Services 会允许您选择所要联机的数据库,因此并不需要提供一个预设的数据库名称。不过,指定一个预设数据库并不会有什么大碍,因为其它的应用程序也有可能会用到这个数据来源名称(DSN)。当您完成后,按 下一步 。
 
 
图29-11 指定预设数据库
7. 接下来的对话框如图 29-12,您可以变更 SQL Server 系统讯息的语言为其它的语言,开启转译功能,指定地区设定,指定长时间执行的查询及驱动程序统计数据的记录文件位置。当您完成设定后,按 完成 。
 
 
图29-12 指定语言及其它设定
8. 出现 ODBC Microsoft SQL Server 设定 对话框,如图 29-13。这个对话框说明了将会建立一个新的 ODBC 数据来源并列出您为该数据来源所选择的所有设定。
 
 
图29-13 「ODBC Microsoft SQL Server 设定」摘要对话框
9. 您应该按 测试数据来源 以测试一下您的设定。当您按下后,就会开始测试到数据库的联机。一旦您成功地完成联机测试,按 确定 ,则这个 DSN 就可开始使用。
________________________________________
说明
SQL Server 必须处于执行的状态才可以设定并测试资料来源。
________________________________________
建立 OLAP 数据库
 
现在您已设定并测试了 ODBC 资料来源,接着可以准备来建立一个 OLAP 数据库。建立 OLAP 数据库也包括将一个现存的数据库设定为 OLAP 数据库。您必须准备指定哪些数据表要用来作为事实资料表,哪些要作为维度资料表。
________________________________________
说明
在本节中,我们会将 Northwind 数据库设定为一个 OLAP 数据库。这个数据库并不具有数据超市或是数据仓储的所有属性,不过我们会利用它来作示范,因为它是内建于 SQL Server,并且这个示范过程可以简单地让您套用在实际应用之中。
________________________________________
在建立 OLAP 数据库的过程中,您会用到分析管理员、Cube 建立精灵、维度建立精灵以及储存设计精灵。要建立该数据库,遵循下列步骤:
1. 按 开始 / 程序集 / Microsoft SQL Server / Analysis Services / 分析管理员 ,出现 分析管理员 窗口,如图 29-14。
 
 
图29-14 「分析管理员」窗口
2. 在左边窗格中展开 Analysis Servers 数据夹,然后展开您的服务器名称数据夹。在服务器名称上按鼠标右键,并在快捷菜单中选择 新增数据库 ,出现 数据库 对话框,如图 29-15。请输入数据库名称并给它一个简介说明。在本例中,我们将数据库命名为 Northwind_OLAP 。
 
 
图29-15 「数据库」对话框
________________________________________
说明
当您展开您的服务器名称数据夹时,会发现分析管理员中已安装了一个范例数据库。如果您在安装 Analysis Services 的过程时,在 选择安装组件 对话框中有选取 范例应用程序 复选框的话,就会自动安装这个名为 FoodMart 2000 的数据库。
________________________________________
3. 按 确定 回到分析管理员窗口。如果您展开 Analysis Servers 数据夹并展开您的服务器名称数据夹,会看到一个新的数据库已被新增进去。(这个数据库已经命名,不过尚未联机至 SQL Server 数据来源,不过别紧张,我们等一下就会开始联机。)展开数据库数据夹(在本例为 Northwind_OLAP 数据夹)可显示数据来源、Cube、共享维度、采撷模型及数据库角色,如图 29-16。
 
 
图29-16 展开 OLAP 数据库
4. 在 Cube 数据夹上按鼠标右键,在快捷菜单中将光标移到 新增 Cube ,并在子选单中选择 精灵 。出现 Cube 建立精灵 欢迎画面,如图 29-17。这个精灵是用来选择要在 Cube 层级上指定的数据来源。
 
 
图29-17 「Cube 建立精灵」的欢迎画面
5. 按 下一步 出现 从数据来源选择一个事实数据表 画面,如图 29-18。要选择 SQL Server 数据库,按 新增数据来源 。
 
 
图29-18 「从数据来源选择一个事实数据表」画面
6. 出现 数据链路内容 窗口,如图 29-19。您可在 提供者 标签中为这个 cube 指定数据来源;不过,在本例中我们要使用 联机 标签来选择我们刚才建立的数据来源。
 
 
图29-19 「数据链路内容」窗口的「提供者」标签
7. 在 数据链路内容 窗口的 联机 卷标(图29-20)中选择数据来源名称(本例为 DataSourceExample),键入联机使用者名称与密码,并输入要使用的初始目录。如果您没有管理员密码(如果您在网络上应该会有),选取 空白密码 复选框。
 
 
图29-20 「数据链路内容」窗口的「联机」卷标
8. 此时您应按一下 测试联机 来测试联机状况。如果测试成功,会有一个联机成功的讯息,如果测试失败,您可能有些部分的输入错误。在联机测试成功后,按 确定 回到 Cube 建立精灵 的 从数据来源选择一个事实数据表 画面,如图 29-21。
 
 
图29-21 已有数据来源及数据表的「Cube 建立精灵」之「从数据来源选择一个事实数据表」画面
9. 在这个画面的 数据来源和数据表 清单中,在您要用来作为 cube 数据来源的数据表上按两下。在本例中,我们在 Orders 数据表上按两下,即使 Orders 资料表实际上并不是一个事实资料表,不过它已经很接近。(此处选择这个资料表主要是让一般使用者可以透过这个范例来练习操作。)
10. 按 下一步 出现 选择定义量值的数字数据行 画面,如图 29-22。此处您可选择一个或一个以上的数据行,以定义为 cube 的数字量值;在汇总时会用到这些资料行。在本例中,选择 OrderID 与 Freight ,您可在这两个数据行上按两下或是按一下向右的箭头选择这两个数据行。
 
 
图29-22 「选择定义量值的数字数据行」画面
11. 按 下一步 出现 选择 cube 的维度 画面,如图 29-23。此处您可选择要用于 cube 的维度数据表。在本例中,我们要建立一个维度数据表。
 
 
图29-23 「选择 cube 的维度」画面
12. 按 新增维度 出现 维度建立精灵 欢迎画面,如图 29-24。
 
 
图29-24 「维度建立精灵」欢迎画面
13. 按 下一步 继续。出现 选择要如何建立维度 画面,如图 29-25。在这个画面中,您可指定要建立维度的方式。您可选择星状结构描述、雪花结构描述、父子式关联、虚拟维度、或是采撷模型。在本例中,选择星状结构描述。
 
 
图29-25 「选择要如何建立维度」画面
14. 按 下一步 出现 选择维度数据表 画面,如图 29-26。本例中我们选择 Employees 数据表作为维度数据表。
 
 
图29-26 「选择维度数据表」画面
15. 按 下一步 出现 选择维度类型 画面,如图 29-27。此处您可选择要使用标准维度还是时间维度。在本例中我们选择 标准维度 。
 
 
图29-27 「选择维度类型」画面
16. 按 下一步 出现 选择维度的层级 画面,如图 29-28。在这个画面中,您可选取数个汇总的层级,不过在这个简单的范例中我们只选取一个层级- Employee Id 。要选择一个层级,可以在要选取的数据行上按两下,或是先选取数据行然后按向右的箭头。
17. 按 下一步 出现 指定成员索引键数据行 画面,如图 29-29。如果您是从多个数据表建立 cube,可在此处指定数据表索引键数据行。
 
 
图29-28 「选择维度的层级」画面

 
 
图29-29 「指定成员索引键数据行」画面
18. 按 下一步 出现 选择进阶选项 画面,如图 29-30。此处您可变更维度、指定成员的排序方式、以及定义储存模式。如果您正在建立的 cube 非常庞大,您应指定 ROLAP 储存模式,就如本章之前所讨论的一般。如果您选取了其中任何一个选项,精灵就会显示出适当的画面来帮助您做决定。此处我们不讨论这些画面。
 
 
图29-30 「选择进阶选项」画面
19. 按 下一步 出现 完成维度建立精灵 画面,如图 29-31。为维度命名后按 完成 。
 
 
图29-31 「完成维度建立精灵」画面
20. 一旦您完成了 维度建立精灵 ,就会回到 Cube 建立精灵 的 选择 cube 的维度 画面(如刚刚的图 29-23 所示),新的维度会出现在 Cube 维度 方块中。在此处,您可选取要用来在事实数据表上建立摘要数据的维度数据表,或是按 新增维度 执行 维度建立精灵 继续建立更多的维度数据表。
按 下一步 继续。如果出现讯息问您是否要计算数据行,按 是 。接着会出现 完成 Cube 建立精灵 画面,如图 29-32。为 cube 命名后按 完成 即可将我们在精灵中所做的一切设定保留下来。

 
 
图29-32 「完成 Cube 建立精灵」画面
21. 按 完成 后会带您到 Cube 编辑器 窗口,如图 29-33。依照需求来编辑 cube,或是按关闭按钮来离开 Cube 编辑器 窗口。一般说来编辑动作并不需要。
 
 
图29-33 「Cube 编辑器」窗口
22. 当您离开 Cube 编辑器 窗口时,会出现一个讯息问您是否要为这个 cube 建立储存体选项,请按 是 ,会出现 储存体设计精灵 欢迎画面,如图 29-34。
 
 
图29-34 「储存体设计精灵」欢迎画面
23. 按 下一步 出现 选择数据储存类型 画面,如图 29-35。此处您可指定数据储存体为多维度、关系型还是使用两种数据型态合并的方式,本例中我们选择 MOLAP 将数据储存在 Analysis Services 的数据结构中。如果您选择关系型OLAP(ROLAP),新的数据表就会储存在您工作的数据库中(本例为 Northwind 数据库)。最后一个选项是 HOLAP(混合式 OLAP),若选取这个选项则数据会留在关系型数据表中,汇总储存于多维度结构中。
 
 
图29-35 「选择数据储存类型」画面
24. 按 下一步 出现 设定汇总选项 画面,如图 29-36。此处您可指定尽力汇总的方式。在本例中,接受默认值 100MB,按 开始 建立汇总。
 
 
图29-36 「设定汇总选项」画面
由于我们在本例中使用的数据表相当小,因此计算汇总只需要几秒钟。汇总结果会被绘制成图表, 设定汇总选项 画面也会再度出现(如图 29-37)。注意在本例中我们还没有作更多的制图,所以这个曲线图只是图表上左侧的一根垂直线。

 
 
图29-37 已绘制汇总图表的「设定汇总选项」画面
25. 按 下一步 出现 完成设计体精灵 画面,如图 29-38。此处您可指定立即完成 储存体设计精灵 或保存设定并等待一些时间。如果您想等到工作时间之后,系统处于低负载时再来建立储存体,这个选项就很有用。在本例中,我们选择 立即处理 。
 
 
图29-38 「完成设计体精灵」画面
26. 按 完成 。出现 处理 对话框,如图 29-39。建立 cube 储存体的作业完成后,画面底部会出现一个讯息,告诉您处理程序已成功地完成了。按 关闭 结束这个程序。
 
 
图29-39 「处理」对话框
修改现存的 OLAP 数据库
 
您可以利用与上述类似的方法,透过分析管理员来修改一个 OLAP 数据库。在本节中,我们将修改 FoodMart 2000 数据库。FoodMart 2000 数据库是 Analysis Services 安装的一部分(如果您在安装过程中有选取 范例应用程序 复选框的话)。要在 FoodMart 2000 数据库中编辑 cube,遵循下列步骤:
1. 在 分析管理员 窗口中,展开 Analysis Servers 数据夹,展开您的服务器,展开 FoodMart 2000 数据夹,然后展开 Cubes 资料夹,如图 29-40 所示。
 
 
图29-40 「分析管理员」窗口
2. 在 Sales 数据夹上按鼠标右键,然后从快捷菜单中选择 编辑 。这会开启 Cube 编辑器 窗口,如图 29-41。这个窗口显示了该 cube 中维度数据表与事实数据表的关联性。
在 Cube 编辑器 窗口中,您可使用列选项来编辑 cube:
o  新增维度 :您可在 维度 数据夹或左边窗格中任何一个维度名称上按鼠标右键,并在快捷菜单中选择 现有的维度 ,即可开启 维度管理员 。 维度管理员 类似于您在本章之前看到的 维度建立精灵 ,可用来新增维度或移除现有的维度。
 
o  移除维度 :您可以在要移除的维度名称上按鼠标右键并选择 移除 ,如此便可将维度从数据库中永久移除。
 
o  新增、删除或重新命名量值 :在量值名称上按鼠标右键选择 新增量值 、 删除 或 重新命名 。
 
o  增导出成员 :在 导出成员 数据夹或任一个导出成员名称上按鼠标右键,选择 新增导出成员 。
 
o  编辑、删除、重新命名导出成员 :在导出成员名称上按鼠标右键并选择 编辑 、 删除 或 重新命名 。
 
在右边窗格的 结构描述 卷标中,您可在维度数据表或事实数据表的标题上按鼠标右键,选择下列选项:
o  插入数据表 允许您将数据表新增至数据库。
 
o  变更别名 允许您重新命名现有的 cube 属性。您可以定义一个以其它 cube 属性为基础来取得的 cube 属性,而不需要改变基础的属性。
 
o  浏览数据 允许您撷取数据表的数据来进行检视。
 
o  取代 允许您选择不同的数据表来取代已存在数据库中的数据表。
 
o  移除(仅有维度数据表) 允许您从数据库中移除维度数据表。
 

 
 
图29-41 「Cube 编辑器」窗口
3. 在 检视 菜单中选择 数据 ,或是在右边窗格中按一下 数据 卷标,可以看得到 OLAP 系统真正的用处。如图 29-42所示,在 Cube 编辑器 窗口的 数据 卷标上,有数个下拉式选单,透过选取这些选单,便可观察以该标准为基础而取得的摘要数据。这些选单是基于 cube 中的维度来建立。 数据 卷标类似于本章稍后会提到的 Cube 浏览器 对话框。
在这个标签中,您可以选取不同的变量组合以达成对数据的不同分析角度。因为摘要资料已经被计算过,所以可以立即得到结果。如果摘要数据无法使用,您将必须执行个别查询。在一个大型的数据超市或数据仓储中,计算汇总可能会需要一段相当可观的时间。

 
 
图29-42 「Cube 编辑器」窗口的数据卷标页
处理数据
 
一旦您建立了 cube,就可以有数个选项让您用来检视及处理数据。这些服务之中,很多可以透过在分析管理员左边窗格中的 cube 名称上按鼠标右键来达成。这些选项包括下列各项:
•   处理 用于更新汇总。当基础数据有所变更时,汇总并不会自动更新,所以必须定期的更新它们。这个处理可能很花时间,因此应当排定执行的周期表(夜间、周末等等)。
 
•   设计储存体 开启 储存体设计精灵 。允许您修正 OLAP cubes 的基本储存体属性。在本章稍早您已经学习过如何使用 储存体设计精灵 。
 
•   使用状况最佳化 开启 使用状况最佳化精灵 ,可帮这您基于已经执行的查询历史记录来改善汇总,进而调校 cube。您可以透过检视已经在数据库上执行的查询,并将那些查询最佳化以完成这个工作。 使用状况最佳化精灵 会提供一些建议方法来修改那些查询或对它们自身进行汇总。
 
•   浏览数据 让您可以检视汇总。 浏览数据 选项会开启 Cube 浏览器 对话框,如图 29-34 所示的 FoodMart 2000 数据库范例。您可以看到,它和 Cube 编辑器 窗口的 数据 卷标很类似。在 Cube 浏览器 对话框中,您可以很容易地利用 cube 储存的汇总建立自订的结果集。
 
•   使用状况分析 开启 使用状况分析精灵 ,让您可以分析那些送往 cube 的查询。 使用状况分析精灵 使用的查询数据,是基于您的标准在 cube 上执行的查询。这个精灵和 使用状况最佳化精灵 很相似,允许您选择基准以判定哪个查询占用的时间最长;不过 使用状况分析精灵 只用来检视数据。
 
Analysis Services 并不会自动更新 OLAP cube,且基础数据会有所变更,所以您必须依照您的需求来决定更新的频率,定期为系统更新这些 cube。如果数据更改的很频繁并且使用者需要最新的信息,您可能就必须不断地更新 cube。如果昨天的数据尚可接受,那么每夜一次更新也许就足够了。
您可以在 OLAP 数据库的 Cube 数据夹上按鼠标右键,并选择 处理所有的 cube ,如此便可更新所有的 cube。一如之前所说的,如果您要个别更新 cube,可在 cube 名称上按鼠标右键并在快捷菜单中选择 处理 。
SQL Server OLAP cubes 不但能透过一个 OLE DB 应用程序来存取,也可以透过分析管理员来检视资料,或者设定一个到 OLAP 数据库的连结。分析管理员的 Cube 浏览器 对话框是一个很有用的工具,可让您基于已建立的 cube 来检视数据。

 
 
图29-43 「Cube 浏览器」对话框
不过,如果您已有一个已经在运作的数据超市或数据仓储,您可能会发现要将 SQL Server Analysis Services 合并到您现有的工作中有点困难,因为 Analysis Services 必须先基于您使用的数据库来建立一个新的数据 cube 才能顺利工作,并且也须经由一个 OLE DB 接口来存取。如果您现在的应用程序不使用 OLE DB,可能就会无法利用这些服务。
如果您需要做多维度分析,Analysis Services 在许多不同类型的数据仓储和数据超市中会是非常有用的。从这些汇总中,您可以使用分析管理员的 Cube 浏览器 对话框来执行多维度分析。您可依照企业的需求,来决定是否利用 Analysis Services 的服务。
本章总结
 
在本章中,您学习了何谓 Analysis Services,以及如何设定它;也学习到如何建立 cube,以及如何在 SQL Server 数据库中维护汇总。本章所讨论的信息应该有助于您决定 Analysis Services 是否对您有用。在下一章中,您会学习到与 SQL Server 管理相关的工具与任务。




28. 合并式复写
合并式复写简介
使用合并式复写
设定合并式复写系统
管理复写
合并式复写的监控与校调
本章总结
合并式复写和交易式复写不同的地方在于,合并式复写可多方作业。利用合并式复写让发行者和订阅者都可以更新发行集。虽然交易式复写也允许订阅者更新发行集,但是这两种复写类型的功能性却有很大的差异。本章中会学到合并式复写的运作方式,以及如何设定、监控与校调合并式复写。
合并式复写简介
 
合并式复写在发行者与一个或多个订阅者之间执行双向复写。这样可以允许数个系统拥有可以更新的发行集副本,并且可以修改自己的发行集副本。在订阅者的修改会被复写至发行者,然后再到其它订阅者。
不像交易式复写,合并式复写的执行方式是在发行者和订阅者安装触发程序。当发行集或发行集的副本有变更时,会触动适当的触发程序,产生复写命令,并队列等待以传送至散发数据库。这个复写命令最后会被送至散发数据库,然后传送到参与复写的系统。基于这样的执行方式,合并式复写会比交易式复写的负担来的大,尤其是在发行者。
在本章中您会学到在合并式复写中两个重要的成员,一个是 合并代理程序(Merge Agent) ,一个是散发数据库。 合并代理程序 会合并自上一次合并后所发生的增量数据变更。当您使用合并式复写时(并不会使用散发代理程序),合并代理程序会与发行者和散发者通讯。快照代理程序只用于建立初始数据库。合并式代理程序会执行以下的作业:
1. 合并代理程序上载所有订阅者变更的数据。
2. 没有冲突的所有数据列会立即上传(这些数据列即为在发行者与订阅者都没有变更的资料列)。有冲突的数据列(这些数据列即为在发行者与订阅者都有变更的资料列)会被送至冲突解决器。 解决器(Resolver) 是一种用来解决合并式复写中产生冲突数据的模块,您可以自行设定适用于自己的解决器。
3. 所有的变更会套用至发行者。
4. 合并代理程序上载所有来自发行者的变更数据。
5. 没有冲突的数据列立即上传;有冲突的送至冲突解决器。
6. 所有变更套用至订阅者。
这个处理过程会依照排程重复执行。在发送订阅模式中,合并代理程序在散发者执行;在提取订阅模式中,合并代理程序在订阅者执行。每一个合并式发行集都有自己的合并代理程序。
使用合并式复写
 
合并式复写适用于需要双向复写的情况,其应用层面十分广泛,其中可允许订阅者修改递增数据这一项就带来了不少好处。以下为合并式复写的应用:
•   公司内部数据共享 :例如一个公司内的负责薪资、应付账款及应收帐款的部门就可以存取一样的数据。每一个部门的使用者可以自行修改数据,然后在部门的系统上,合并所有的修改。
 
•   多点资料共享 :当不同地点的使用者需要用到相同的数据,并且需要修改数据时,就可利用到合并式复写。
 
•   讯息传递 :合并式复写可当作是讯息传递的系统,可以修改数据并将变更后的数据传送回到原系统。
 
设定合并式复写系统
 
设定合并式复写和设定快照式与交易式复写类似。首先必须设定发行集,然后将发行集以发送或提取的方式供订阅者订阅。
________________________________________
说明
在设定任何类型的 SQL Server 复写之前,您必须先设定发行与散发。请参阅 第26章的〈设定发行与散发〉 一节的叙述。
________________________________________
设定发行集
 
设定合并式复写发行集的过程和之前两种类型的发行集略有不同,以下为设定的步骤:
1. 使用 Enterprise Manager,透过下列任一步骤执行设定,选择 工具 / 复写 ,按一下 建立和管理发行集 ;或是选择 工具 / 精灵 ,选择 建立发行集精灵 。用任一方式都可进入建立和管理发行集的对话框,如图28-1 所示。这里可选择预发行的数据库或数据表。
 
 
图28-1 「建立和管理发行集」对话框
若发行集已存在,下列的按钮就会显示:
o  发送新的订阅 :您可以为已经存在的发行集建立新的发送订阅,这个步骤将会在本章的 〈设定订阅〉 一节讨论。
 
o  属性与订阅 :可更改发行集与订阅属性。
 
o  指令化发行集 :可建立指令码用以建立更多发行集。
 
o  删除发行集 :可以删除已经设定的发行集。
 
2. 选择发行集数据库(如图28-1,选择 Northwind 为发行集数据库),选择 建立发行集 进入 欢迎使用建立发行集精灵 窗口,如图28-2所示。选取 显示这个精灵中的进阶选项 选项。
 
 
图28-2 「建立发行集精灵」的欢迎窗口
3. 按一下 下一步 进入 选取发行集的数据库 窗口,如图 28-3 所示。可再次选择欲发行的数据。在步骤二选取的数据库会反白显示。
 
 
图28-3 「选取发行集的数据库」画面
4. 按一下 下一步 进入 选取发行集类型 画面,如图28-4 所示。
 
 
图28-4 「选取发行集类型」画面
您可以选择任一复写类型,三种发行集的功能如下:
o  快照式发行集 :可以周期性的复写发行项的快照集至订阅者。您可以使用任何资料表建立快照式发行集。
 
o  交易式发行集 :可以建立交易式复写发行集,该发行集会以发行者的变更来更新订阅者数据。只有数据表有主索引键时,才可以建立交易式复写的发行项。
 
o  合并式发行集 :可以建立合并式复写发行集,该发行集允许您在发行者与订阅者之间双向复写。您可以使用任何数据表建立合并式复写的发行项。
 
5. 按一下 合并式发行集 ,按一下 下一步 进入 指定订阅者类型 窗口,如图28-5 所示。这个窗口可以指定是否所有的订阅者执行 SQL Server。图28-5显示默认值,预设的设定指定所有的订阅者都执行 SQL Server 2000。如果接受此设定值,就是将复写设定为使用原生 SQL Server 2000 的数据类型。其它还可以选择 SQL Server 7.0 的服务器,或其它性质的服务器,这个选项会使复写数据转换回字符格式,当然也会经过一些繁杂的转换手续。
 
 
图28-5 「指定订阅者类型」窗口
6. 按一下 下一步 进入 指定发行项 画面,如图28-6 所示。在这个画面中,可以指定将资料表或其它数据库对象当作发行项以进行复写。这些发行项构成您所建立的发行集。在左边所列出的画面,可以在 显示 中复选所列出的项目,包括 数据表 、 预存程序 及 检视表 ,一旦选取任何一个项目,在右边的窗口就会列出这些项目的明细。然后您可以在右边的明细中再选取想要发行的数据表,或是回到左边的窗口,选取 全部发行 项目中的所有数据表。记住,每一个数据表、预存程序或检视表都视为一个独立的发行项,而发行集是由一组发行项构成。
 
 
图28-6 「指定发行项」画面
________________________________________
说明
若在订阅者已存在预存程序,可以利用复写呼叫预存程序,而不需要在网络上传递预存程序的结果。
________________________________________
7. 由于选择的是合并式复写,我们可以替发行项定义更多的属性。按一下 [...] 按钮即可进入 数据表发行项属性 画面设定属性,如图28-7 所示。
您可以透过这个窗口中的卷标页为发行项设定不同的属性,图28-7 即为 一般 标签页。这里可以指定发行项名称与来源数据表拥有者,并且决定数据冲突的定义。预设选项会将同一数据行进行变更视为冲突。

 
 
图28-7 「数据表发行项」属性中的「一般」标签页
8. 选择 解决器 标签页可指定解决器,如图28-8 所示。如果使用预设的解决器,当冲突发生时,发行者会被视为是胜利的一端。还有,如果在订阅者之间发生冲突,则首先进行同步的订阅者就会被视为是胜利者(而稍后执行的其它订阅者则会被视为是失败端)。您也可以选择其它的解决器或是自订的解决器。
9. 在 合并变更 标签页中(如图28-9),您可以对特定的操作,指定额外的安全性。藉由在 检查使用权限 中选取一个或多个选项,您可以指定合并代理程序的权限以执行特定的操作,或者指定在执行某些操作前先检查。另外,该卷标页中有预设的选项,指定了多重数据行更新的方式,请接受这个默认值。按一下 确定 继续设定。
 
 
图28-8 「数据表发行项」属性中的「解决器」卷标页窗口

 
 
图28-9 「数据表发行项」属性中的「合并变更」窗口
10. 按一下 下一步 。检查发行集后的结果会在这里显示,最可能看到的窗口会如图28-10 所示。合并式复写需要一个唯一的识别数据行,这个数据行会自动的帮您加入到数据表内。另外,在识别数据行上将会建立 NOT FOR REPLICATION 选项。
 
 
图28-10 「发行项的问题」画面
11. 按一下 下一步 进入 选取发行集名称与描述 画面,如图28-11 所示。在这个画面中,简单的指定发行集名称与描述即可。
12. 按一下 下一步 进入 自订发行集的属性 画面,如图28-12 所示。在这个画面中可以决定是否需要定义资料筛选或自订其它发行集的属性,选择 否,依指定建立发行集 。
 
 
图28-11 「选取发行集名称与描述」画面

 
 
图28-12 「自订发行集的属性」画面
13. 选择 下一步 进入 完成建立发行精灵 画面。按一下 完成 ,就可看到精灵建立发行集的过程,执行完毕后发行集即成功的建立。
现在检查 复写监视器 的 合并数据代理程序 数据夹,并不会有任何数据出现,这是因为合并代理程序是用于双向复写,因此在复写之前需要先设定订阅者。在订阅者设定完成后,合并代理程序才会出现在复写监控器的数据夹中。
设定订阅
 
就如同之前两种类型的设定一样,设定合并式复写的最后一个步骤就是设定订阅者。首先必须在散发数据库中启用订阅者,启用的方法以在 第26章的〈启用订阅者〉 一节中介绍过。然后在订阅者或发行者设定订阅,从订阅者可设定提取订阅,而从发行者则可设定发送订阅。
设定提取订阅
 
设定提取订阅的方式在 第27章的〈设定提取订阅〉 一节中有介绍设定的步骤,由于设定的过程几乎一模一样,因此在这里只简单的带过设定的步骤。
1. 进入 提取订阅精灵 。
2. 进入 欢迎使用提取订阅精灵 画面。
3. 按一下 下一步 进入 寻找发行集 画面,在这个范例中选择在已注册服务器的服务器中寻找发行集。
4. 按一下 下一步 进入 选取发行集 画面,并且选择要使用的发行集。
5. 按一下 下一步 进入 指定同步代理程序登入 画面,指定代理程序联机到发行者时的方式和登入账号。
6. 按一下 下一步 进入 选取目的数据库 画面,指定复写的发行项要放在哪个数据库中。
7. 按一下 下一步 进入 初始化订阅 画面,选择适当的选项。
8. 按一下 下一步 进入 快照集传送 画面,选择快照集传送位置。
9. 按一下 下一步 进入 设定合并代理程序排程 画面。这个画面的设定和 第27章 中的 设定散发代理程序排程 类似,可参照之前的设定逻辑选择适合选项。
10. 按一下 下一步 进入 设定订阅的优先权 画面,如图28-13 所示。优先权的意思是说当冲突发生时有哪些订阅集会优先被认为是正确的。预设的设定(也是建议的设定)指定当冲突发生时,在发行者的设定会优先被用来解决冲突。
11. 按一下 下一步 进入 启动必要的服务 画面,并且启动未被启动的 SQL Server 代理程序。
12. 按一下 下一步 进入 完成提取订阅精灵 画面,检视设定确定无误后,选择 完成 即可完成订阅集的设定作业,现在提取订阅会定期更新。
 
 
图28-13 「设定订阅的优先权」画面
设定发送订阅
 
发送订阅要在发行者启动,您可以使用 发送订阅精灵 来设定。请参照以下步骤使用 发送订阅精灵 :
1. 使用以下任一方法进入 发送订阅精灵 。第一种方法是在 Enterprise Manager 中按一下 工具 ,选择 复写 / 将订阅发送至其它服务器 ,进入 建立与管理服务器的发行集 对话框,如图28-14 所示。
 
 
图28-14 「建立与管理服务器的发行集」对话框
在 数据库与发行集 中选择一个发行集,并按一下 发送新的订阅 按钮。要使用第二种方法进入图28-14 的对话框,请在工具列中选择 工具 ,在选取清单中选择 精灵 ,然后展开 复写 ,并选择 建立发送订阅精灵 。
2. 按一下 发送新的订阅 后,会看到如图28-15 的 欢迎使用发送精灵 画面。
 
 
图28-15 「欢迎使用发送精灵」画面
3. 按一下 下一步 进入 选择订阅者 画面,如图28-16 所示。这里可以指定发行集要发送至哪一个订阅者。在 启用的订阅者 清单中选取订阅者。
 
 
图28-16 「选择订阅者」画面
4. 按一下 下一步 进入 选取目的数据库 画面,如图28-17 所示。这里可以指定订阅者的数据库,您可以选择已经存在的数据库,或是依需要建立新的数据库。按一下 浏览或建立 按钮可以看到已经存在数据库的清单。如要建立新的数据库,在按一下此按钮后可再按一下 建立新对象 ,然后在 数据库属性 的窗口中建立新的数据库。
5. 按一下 下一步 进入 设定合并代理程序的位置 画面,如图28-18 所示。指定合并代理程序执行的位置,选择接受默认值即将合并代理程序在散发者执行,您也可以选择在订阅者执行代理程序。除非散发者的工作非常忙碌,否则建议接受默认值。
 
 
图28-17 「选取目的数据库」画面

 
 
图28-18 「设定合并代理程序位置」画面
6. 按一下 下一步 进入 设定合并代理程序的排程 画面,如图28-19 所示。在这里可以选择连续更新订阅集或选择依排程更新订阅集。选择依排程更新订阅集,按一下 变更 按钮可进入 编辑重复执行作业排程 对话框更改排程及更新订阅集的频率。记住如果选择的是连续更新,会造成系统的负担。
 
 
图28-19 「设定合并代理程序的排程」画面
7. 按一下 下一步 进入 初始化订阅 画面,如图28-20 所示。在这里可以指定订阅集是否需要初始化。初始化结构描述和在订阅者的数据集已经由预设指定。如果结构描述已经存在,就无法选取 否, ...这个选项。这个画面中也可以启动快照集代理程序,建议在初始化快照集时就启动快照集代理程序,否则就必须手动启动代理程序。一旦启用了快照集并且开始进行复写,在新的订阅建立之前都不会使用到快照集。每建立一次新的订阅,就要建立新的快照集。
8. 按一下 下一步 进入 设定订阅的优先权 画面,如图28-21 所示。这里可以设定当冲突发生时订阅的优先权。建立接受默认值,也就是当冲突发生时,发行者的设定会有优先权。
 
 
图28-20 「初始化订阅」画面

 
 
图28-21 「设定订阅的优先权」画面
9. 按一下 下一步 进入 启动必要的服务 画面,如图28-22 所示。在这里可以启动还未启动的 SQL Server 代理程序。
 
 
图28-22 「启动必要的服务」画面
10. 按一下 下一步 进入 完成发送订阅精灵 画面,如图28-23 所示。检查所有的设定是否正确后,按一下 完成 开始将快照集复制到订阅者的程序。您会看到一个描述程序进行的对话框,最后会出现操作程序完成的消息框。当精灵完成后,发送订阅就建立,且会定期更新。
 
 
图28-23 「完成发送订阅精灵」画面
管理复写
 
在了解如何在 SQL Server 2000 环境中建立与设定复写数据库后,现在可以来学习利用 Enterprise Manager 的监控功能与设定选项,管理与疑难排除当复写不能如预期执行时的问题。
复写代理程序的监控与管理
 
在 Enterprise Manager 中的 复写监视器 数据夹可以找到 代理程序 。请参照以下步骤存取代理程序:
1. 展开服务器群组、您的服务器,及复写监视器数据夹。
2. 如果展开的是发行者服务器, 发行者 和 代理程序 数据夹会出现在 复写监视器 数据夹中。 发行者 数据夹内包含属于此服务器的所有发行者。 代理程序 数据夹内含有 快照集代理程序 、 散发代理程序 、 合并代理程序 ,及用在清除和历程记录数据的 其它代理程序 。
3. 虽然代理程序通常不需要被手动启动或停止,但需要时可使用 复写监视器 来执行。如果复写系统并未依照设定执行,很可能是由于使用预设的选项而没有立即启动快照集代理程序。(这就是为什么之前在设定过程中我们建议选择立刻执行初始快照集)。在 Enterprise Manager 中按一下代理程序数据夹,检查代理程序的状态,并在右方窗格中检示有关代理程序的信息,如图28-24 所示。这里可以决定是否执行某个代理程序,也可以看到是否该代理程序正在使用中。当启动了某个代理程序,代理程序会执行直到任务完成,然后停止作业。接者,SQL Server 代理程序会依排程复写代理程序。
 
 
图28-24 Enterprise Manager 中的合并代理程序
4. 在代理程序中按右钮呼叫快捷菜单,在这里有几个可以提供监控和管理代理程序的选项,如图28-25 所示。
这些选项的简介如下:
o  错误详细数据 :列出所有曾经发生的错误清单。
 
o  代理程序历程记录 :列出代理程序活动。
 
o  代理程序属性 :让您修改复写代理程序的排程、数据库存取方式、代理程序的步骤,以及作业完成后的执行动作,例如可以选择让系统以电子邮件通知您代理程序执行事件的完成。
 
o  代理程序设定文件 :可以检视及修改代理程序参数,例如登入逾时断线时间、批次操作大小,以及查询逾时断线时间的设定等。
 
o  在订阅者端执行代理程序 :可指定在订阅者执行代理程序。
 
o  在散发者端执行代理程序 :可指定在散发者执行代理程序。
 
o  启动代理程序与停止代理程序 :可以启动或停止代理程序。
 
o  重新整理速度和设定值 :可以修改重新整理执行监控数据的频率。
 
o  选取字段 :可以指定结果集中想要检视的数据行。
 
o  显示匿名订阅 :指定是否在窗口中显示匿名订阅。
 
o  说明 :提供关于此窗口的说明信息。
 

 
 
图28-25 合并代理程序选项
设定合并代理程序
 
建立发行集后,可能会需要修改合并代理程序的行为模式。举例来说,你可以指定合并代理程序的启动模式。在连续模式中,合并代理程序在 SQL Server 代理程序启动后也一并启动。而在依照排程执行的模式中,合并代理程序会依照您指定的排程启动,完成读写交易记录文件中复写的交易就停止。更改模式和其它的属性可以提高执行效能,并降低发行者的负担。以下为设定合并代理程序的步骤:
1. 在 Enterprise Manager,展开想要修改的服务器,展开 复写监视器 数据夹,展开 代理程序 后选择 合并代理程序 数据夹。
2. 在右边的窗格中,选取发行集按右钮以呼叫快捷菜单,接着选择 代理程序属性 。
3. 合并代理程序属性窗口出现,如图28-26 所示。
 
 
图28-26 「合并代理程序属性」窗口中的「一般」标签页
4. 选择 步骤 标签页,如图28-27 所示。在卷标页,我们可以看到合并代理程序执行的步骤,这些步骤执行的动作各为:
o  记录读取代理程序启动讯息 :将讯息记录在 记录读取代理程序 的历程记录中(在散发数据库的MSLogreader_histroy数据表中)。
 
o  执行代理程序 :依指定的排程启动代理程序,当执行模式为连续时,代理程序会在系统结束时才停止执行。
 
o  侦测非记录性代理程序的结束 :将代理程序事件失败的讯息放在记录读写器代理程序的历程记录中。
 
5. 选择 执行代理程序 步骤选择 编辑 按钮进入 编辑作业步骤 对话框,如图28-28 所示。在这个对话框可以设定如何启动合并代理程序。
 
 
图28-27 「合并代理程序属性」窗口中的「步骤」标签页

 
 
图28-28 「编辑步骤」对话框中的「一般」标签页
合并代理程序可以设定很多选项。预设的合并代理程序参数可在本步骤中的 命令 方块及 复写代理程序设定文件的详细数据 对话框中变更(稍后会介绍)。可变更的两项参数如下:
o  Contunuous :指定是否合并代理程序以连续模式或依排程执行。删除参数即可将合并代理程序依排程执行。
 
o  DistributorSecurityMode :指定合并代理程序使用 SQL Server 或 Windows NT 模式验证。
 
另外,您也可以在 编辑 对话框中指定其它参数,例如Login Timeout、Buffers、Polling Interval、Query Timeout、散发者和发行者信息及Output。
________________________________________
相关信息
关于这些参数的设定可以在 SQL Server《在线丛书》中找到数据。在 索引 卷标页中输入 合并代理程序 后选择 启动 主题即可。
________________________________________
6. 完成 合并代理程序属性 的修改后,按一下 确定 储存修改。
透过 合并代理程序设定文件 ,可以修改其它的选项,请按照下列的步骤:
1. 在 Enterprise Manager 左边的窗格中,展开 合并代理程序 ,选定发行集后按右钮,叫出快捷菜单,选择 代理程序设定文件 ,如图28-29 所示。
 
 
图28-29 「合并代理程序设定文件」对话框
注意此对话框所包含的选项比记录读取器代理程序( 第27章 中有介绍)还多。这些设定文件提供了功能范围,让您可选择一个最适合系统的设定文件。
2. 按一下 新增设定文件 按钮以建立一个新的设定档。现有的设定档不允许修改。按下按钮后会看到如图28-30 的画面。
 
 
图28-30 「复写代理程序设定文件的详细数据」对话框
3. 在此对话框中,可以修改以下的参数:
o  BcpBatchSize :在大量复制作业中传送的数据列数目。在套用结构描述变更的作业中执行 bcp 时,「合并代理程序」会使用批次大小来决定记录进度讯息的时间。数值 0 表示未记录任何讯息。
 
o  ChangesPerHistory :记录上传和下载讯息的临界值。
 
o  DownloadGenerationsPerBatch :自「发行者」下载变更至「订阅者」时,单一批次中处理的世代数目。世代被定义为每个发行项的变更的逻辑群组。不可靠通讯连结的默认值为 10。
 
不过,在各种状况下,每个批次所处理的实际世代数目,会等于 UploadGenerationsPerBatch 设定与已发行的发行项数目加一之间的较大值。
o  DownloadReadChangesPerBatch :自「发行者」下载变更至「订阅者」时,单一批次中读取的变更数目。
 
o  DownloadWriteChangesPerBatch :自「发行者」下载变更至「订阅者」时,单一批次中套用的世代数目。
 
o  FastRowCount :指定验证数据列计数时所用的数据列计数方法的型别。数值 1(默认值)表示使用快速的方法;数值 0 表示使用完整数据列计数的方法。
 
o  HistoryVerboseLevel :在合并作业期间记录的历程的数量可为:
 
 总是更新相同状态先前的历程讯息(启动、进行、成功等)。若无相同状态的先前记录,则插入新纪录。这一层级会记录最小的讯息数目。
 
 插入新的历程记录,除非此记录用于类似闲置(Idle)讯息或长期执行的工作讯息的项目中,此时会更新先前的记录。这一层级会记录层级 1 的讯息,以及其它进行中的讯息。
 
 总是插入新的记录,除非它是闲置(Idle)讯息。
 
可以设定ChangesPerHistory参数,使历程记录对效能的影响减至最小。
o  KeepAliveMessageInterval :历程执行绪检查是否有联机在等待服务器响应之前的秒数。可以增加这个值,以避免长期执行批次时,代理程序遭检查代理程序标示为可疑。
 
o  LoginTimeout :在代理程序逾时之前尝试登入的秒数。
 
o  MaxDownloadChanges :在指定的合并工作阶段期间,想要下载的最大变更的数目。由于要处理完整的世代,因此下载的资料列数目可能超过指定的最大值。
 
o  MaxUploadChanges :在指定的合并工作阶段期间,想要上传的最大变更的数目。由于要处理完整的世代,因此上传的资料列数目可能超过指定的最大值。
 
o  MaxDeadlockRetries :合并处理序在遭遇死结(Deadlock)时重新尝试内部作业的次数。可为介于 1 和 100 之间的任何值。
 
o  PollingInterval :在连续模式下,「发行者」或「订阅者」查询数据变更的秒数。
 
o  QueryTimeout :在代理程序逾时之前发出查询的秒数。
 
o  UploadGenerationsPerBatch :自「订阅者」上传变更至「发行者」时,单一批次中处理的世代数目。世代被定义为每个发行项的变更的逻辑群组。不可靠通讯连结的默认值为 1。
 
不过,在各种状况下,每个批次所处理的实际世代数目,会等于 UploadGenerationsPerBatch 设定与已发行的发行项数目加一之间的较大值。
o  UploadReadChangesPerBatch :自「订阅者」上传变更至「发行者」时,单一批次中读取的变更数目。
 
o  UploadWriteChangesPerBatch :自「订阅者」上传变更至「发行者」时,单一批次中套用的变更数目。
 
o  Validate :指定在合并工作阶段结束时是否要加以验证,若是如此,则该验证是何型别。数值 0(默认值)表示无验证。数值 1 表示是仅限资料列计数的验证。数值 2 表示是资料列计数和加总检查码(Checksum)验证。数值 3 表示二进制加总检查码验证(仅可用于 SQL Server 2000)。
 
o  ValidateInterval :设定为连续模式时,验证此订阅的分钟数。
 
如果合并式复写是依排程模式执行,就会由 SQL Server 代理程序启动,并且会在结束之前,依MaxUploadChanges及MaxDownloadChanges的指定,处理更改的次数。
停用复写
 
利用 Enterprise Manager 可停用所有或部分的复写,只要在 Enterprise Manger 的复写精灵中移除选取的复写组件即可。本节会学习如何简单的执行这项作业。
移除发送订阅
 
在散发者系统中,使用Enterprise Manager的发送订阅精灵就可移除发送订阅。在启动发送订阅精灵后就会出现 建立与管理发行集 对话框,按一下要删除的订阅后,按一下右方 删除发行集 的按钮,出现提示方块,询问是否确认删除此订阅。按一下 是 即可移除订阅。
移除提取订阅
 
在订阅者系统中,使用 Enterprise Manager 的提取订阅精灵就可移除提取订阅。在启动提取订阅精灵后会出现 建立与管理发行集 对话框,按一下要删除的订阅后,再按一下右方 删除发行集 的按钮,出现提示方块,询问是否确认删除此订阅。按一下 是 即可移除订阅。
移除散发和发行
 
要移除散发和发行,必须开启 停用散发暨发行精灵 。在停用精灵的第一个画面,必须指定是否停用所有散发及发行,或只移除发行。如果选择的是第一个选项,服务器上所有的发行集、订阅和散发者都会被移除;如果选择的是第二个选项(预设选项),就只有发行集会被移除。在选项决定后,会出现确认画面,按一下 是 按钮后就会移除所选的复写组件。
合并式复写的监控与校调
 
本节将学习如何监控和校调合并式复写系统,使其以最佳化执行。另外也会介绍合并式复写系统的设定要点,以及合并式复写的属性。
合并式复写的属性
 
合并式复写和其它两种类型的复写方法不太相同,最大的不同处在于合并式复写不采用单向的复写方法,在发行者或任何订阅者都可以进行修改。另外,交易式复写的交易记录文件是被读取以追踪变更,属于 SQL Server 的外部操作;合并式复写则是在复写数据表中建立触发程序来追踪变更。
在首次执行合并式复写时会利用到快照集,不过只会发生一次,因此不需校调快照式复写处理过程。合并式复写同时在发行者与散发者建立数据表,以执行复写。另外,一个 GUID 数据行会被新增至复写的每一个数据表中,这样可以唯一的辨识出每一个数据列,因此复写代理程序才能追踪受影响的变更。
当插入或修改数据列,触发程序会标记该数据列以供复写,日后当合并代理程序被启动时,就会将所有标记的数据列送至散发者数据库以供复写。同时,在订阅者系统中被修改过的数据列,也会由合并代理程序将修改更新至发行者。这样就完成了双向的复写程序。
设定合并式复写
 
合并式复写需要正确的设定所有参与系统的 I/O 子系统。网络对改善复写执行效能也非常的重要。设定正确的批次操作大小也很重要。如果增加批次操作大小,每个批次操作的内容增多,档案数量较少,这样的设定较有效率。此外,您还可以校调快照式复写。不过,由于快照集应用程序只作用一次,因此可以跳过这个步骤。最后您可以修改合并代理程序,这个修改程序在本章稍早有提及。本节将介绍的是 I/O 与合并式批次操作容量的设定。
设定足够的 I/O 容量
 
若是 I/O 的容量足够,就能增进复写过程的效能。如同其它的 SQL Server 系统,系统中负责记录复写的交易记录文件应该放在自己的 RAID 1 磁盘区中以便保护数据,而数据文件则应该放在一个或数个 RAID 10 或 RAID 5 磁盘区。和交易式复写相同的地方在于,合并式复写只需微幅的调整标准 I/O 设定。
 在发行者设定 I/O 子系统 一般来说,在设定发行者的 I/O 子系统时,应遵照本书中不断提及的重点来设定。和交易式复写不同的地方在于,合并式复写不会增加交易记录文件的负担,只要遵照一般的要点作设定即可。
 在散发者设定 I/O 子系统 散发者数据库的交易记录文件应设定在 RAID 1 磁盘区。这样可使得散发者数据库的记录文件达到最佳执行效能,改善散发者的执行效能。
 在订阅者设定 I/O 子系统 由于合并式复写是双向的进行,因此订阅者和发行者的校调方式类似,只要遵照一般的要点作设定即可。
设定合并批次操作容量
 
在繁忙的系统中,您可以利用设定合并批次操作容量的方式改善复写执行。合并批次操作容量决定了单一批次操作中要复写多少有变更的数据列。如果增加批次操作容量,每个批次操作的内容增多,档案数量较少,这样的设定较有效率。
监控合并式复写系统
 
监控交易式复写活动的方式可透过效能监视器。效能监视器在安装 SQL Server 复写时会加入一些对象,对象如下:
•   SQLServer:Replication Agents :计算现在系统中有几个不同类型的代理程序正在执行。
 
•   SQLServer:Replication Merge :提供关于合并式复写的速率数据,包括每秒中冲突、上载与下载次数。请注意这些信息并不会真的一定有办法辅助校调合并式复写。
 
利用效能监视器来监控这些值可让您了解是否散发者有执行效能上的困难。虽然这些效能监视器数据提供很多有用的信息,但并不一定可找出真正的问题。校调合并式复写最好的方法还是注意网络的执行效能,检查可能会产生网络效能瓶颈的地方。参照前两章的要点,检查散发者的负载是否过重。
校调合并式复写系统
 
校调合并式复写系统最主要的步骤就是正确的设定和监控系统,这些在前一节中已提及。透过效能监视器监控您的系统,注意网络的效能。不过,对合并式复写数据来说,效能监视器所提供的数据就不是那么有用。反而可能要参考其它 SQL Server 的计数器和 Microsoft Windows 2000 的计数器来校调系统。
 第24章 曾经提到,当系统的更新次数频繁,可能需要修改 BCP 批次操作容量和合并式批次操作容量。如果增加 BCP 批次操作容量大小,原来快照集代理程序的执行效能也会增加。如果增加合并批次操作容量,由于每个批次操作的内容增多,档案数量较少,影响系统的次数也减少,是较有效率的设定。不过在复写时会增加较多的工作量。
此外,您可以变更轮询频率,变更轮询频率可以使合并式复写执行的频率增加或减少。不过若非必要,并不建议这种变更。如果要校调轮询时间,试着先变更批次操作容量。
如有必要,还要监控网络是否可承载负荷。如果系统并不是执行的很顺,举例来说,如果 CPU 和 I/O 子系统达到饱和,或是复写过程的时间过长,就可能是网络出了问题。网络的问题就比较棘手,因为网络的问题不是检查效能监视器就可以,可能要用到如 Microsoft System Management Server(SMS)这样的网络监控产品才可以监控网络卡是否已达饱和。如果网络卡已达饱和,解决的办法就是购买更快的网络卡,或是新增一条专属的网络供复写、备份和复原来使用。不论是发行者、散发者或是订阅者,都属于 SQL Server 系统。所以校调这些系统的方式就如同校调 SQL Server 系统时所应注意的要点。
本章总结
 
本章为复写系列的最后一章,在本章中您应该已经学到合并式复写的执行,及合并式复写的用途。另外,也学习如何正确的设定、监控与校调合并式复写。在下一章中我们将学习 Microsoft Analysis Service 的使用。





    摘要:交易式复写概观 交易式复写的应用设定交易式复写系统设定、监视与校调散发者交易式复写校调执行交易式复写    (全文共22125字)——点击 此处阅读全文


2005年12月30日

26. Microsoft SQL Server 复写:概观与快照式复写
什么是数据库复写?
复写概念
设定发行与散发
快照式复写
管理复写
快照式复写校调
本章总结
Microsoft SQL Server 数据库复写技术可用于散发数据和预存程序在不同的服务器,复写允许设定系统自动地将数据复制到另一个系统。使用数据库复写,您可依您的需求决定应复制数据的多寡,并且可决定要把数据分配到多少个系统里。由于复写程序是自动的,并且复写期间数据库会将复写的状态数据及复写数据都储存下来,因此不用担心数据遗失的问题。如果复写程序被中断(如断电),在系统恢复正常运作后,复写会从中断处继续进行。
由于复写的程序相当复杂,本书以三章来讨论这个主题。本章会先学到复写与快照式复写的基本方法与概念, 第27章 会介绍交易式复写, 第28章 则介绍合并式复写,这三章提供的信息将可让您彻底了解 SQL Server 复写,包括如何规划、管理与使用。
什么是数据库复写?
 
 数据库复写(Database Replication) 是一种从一个数据表或数据库将数据复制或复写到另一个数据表或数据库的动作。使用复写,您可以完整或指定部份的数据库复本,分散到公司内部的其它系统。当使用 SQL Server 复写,分配和复制数据的任务即自动进行,在复写数据的过程中也不需要使用者的介入。由于数据复写与程序是由 SQL Server 内部来完成,因此具备了稳定性与可复原性。如果复写期间(或是任何 SQL Server 交易进行期间)产生错误,作业会在问题修复后从中断处继续执行。因此,许多人利用复写取代其它在系统间搬移数据的方法。
有许多选项可用来规划网络上的复写。例如,您可指定要复写的数据多寡。您可指定复写的复本是只读还是可修改。也可指定数据每隔多久就需要复写。在 〈规划快照式复写〉 一节里将介绍这些与其它的选项。
复写概念
 
本节将学习基本的数据库复写概念。首先了解发行和订阅模型,以及复写的三种类型:复写数据、数据传播以及复写代理程序。
复写组件
 
Microsoft SQL Server 2000 中的复写是利用「发行和订阅(publish-and-subscribe)」模式,这个模式首先在 SQL Server 6.0 中被用来建置数据的复写,主要包括三个观念,即 发行者(publishers) 、 散发者(distributors) 和 订阅者(subscribers) 。「发行者」是使资料可供复写的数据库系统;「散发者」是包含分散数据库或虚拟数据(pseudodata)来维护和管理复写的数据库系统;「订阅者」是接受复写数据和储存复写数据库的数据库系统。
发行者
 
发行者是由一个安装有 SQL Server 数据库的 Microsoft Windows 系统组成。此数据库是被复写数据的来源。此外也会侦测已经变更的数据,使数据确实的被复写。发行者也需维护该站台中关于发行集的所有信息,例如哪些数据被规划复写等等。依复写类型的不同,发行者在复写过程依需要负担不同的工作量,本章稍后将有进一步解释。
一个复写环境可以包含很多订阅者,但任何要给予发行的 发行项(article) ,亦即规划要复写的资料集,只能有一个发行者。(发行项将在本章稍后 〈复写资料〉 一节里详细说明。)一个特定的资料集只能有一个发行者,并非意味着发行者是唯一一个可修改数据的组件,订阅者也可修改数据甚而再发行数据,不过这需要一点技巧,您可参阅本章及后两章。
散发者
 
散发者是包含散发数据库和储存中继数据、历程记录数据及其它信息的服务器;散发者也需负责将复写资料散发给订阅者。发行者和散发者并不需要放在同一台服务器上,事实上,您可能会比较喜欢用一台专用的服务器来担任散发者。当建立发行者时,每个发行者必须指派一个散发者,且一个发行者只能有一个散发者。这种安排方式将在本章稍后 〈规划发行与散发〉 一节里有详细的说明。
________________________________________
说明
 中继资料(metadata) 是关于数据的概要数据,用来在复写中追踪复写作业的状态。该数据同样会由发行者传播给复写集合中的其它成员,内容包括数据结构与数据属性的相关信息,如某一数据行中数据的型别(数值型态、文字型态等)或数据行的长度等。
________________________________________
订阅者
 
刚才已经提到,订阅者是储存复写数据和接收更新的数据库服务器。订阅者也可进行更新并和发行者一样对其他系统提供服务。同时,一个订阅者也可以作为其它系统的发行者。要让订阅者接收复写数据,它必须订阅该数据。「订阅复写」(subscribing to replication)指的是订阅者接收该数据的规划方式。而一个「订阅」(subscription)意指您所订阅的数据库信息。我们在本章的 〈规划快照式复写〉 一节中将讨论这些组件之间的相互关连性。
复写类型
 
SQL Server 提供了三种类型的复写:快照式(snapshot)、交易式(transactional)和合并式(merge)。这些复写的类型提供了复写数据库中不同程度的数据一致性,同时也会有不同层级的系统负荷。
快照式复写
 
快照式复写是最简单易懂的复写类型。在快照式复写中,数据库的快照集(snapshot)将周期性地产生并传播给订阅者。快照式复写的最主要的优点在于,它不涉及到发行者和订阅者之间持续的系统负荷;也就是说,它不需要连续的监控发行者上的数据变更,也不需持续传送数据至订阅者。最大的缺点在于,目前存在于订阅者上的数据库不一定是最新的快照集。
在很多情况下,快照式复写已经足够并且合适。举例来说,当来源数据的修改只是偶尔为之的时候,像电话清单、价格表和项目描述等信息,可以很容易的使用快照式复写来处理,这些清单可以在每天的业余时间进行更新。
交易式复写
 
交易式复写可用来将变更复写至数据库。使用交易式复写,任何发行项(规划要复写的数据集)的变更将立即从交易记录文件中被撷取出来并传播至散发者。依照您复写的规划,利用交易式复写可让您的发行者与其订阅者保持近乎一致的状态。
当需要保持所有复写系统为最新状态时,应使用交易式复写。由于每个造成系统中数据变更的交易均会个别套用至复写系统,交易式复写比快照式复写占用更多的系统资源。不过,交易式复写比快照式或合并式复写更能保持系统在最新的状态。交易式复写将在 第27章 详细说明。
合并式复写
 
合并式复写与交易式复写类似的地方在于它会持续追踪发行项的变更。不过,合并式复写并不会个别的传播造成变更的交易,而是周期性的传送一整批变更。由于合并式复写以批次方式传送数据,它也类似于快照式复写。(虽然在快照式复写中,所有规划要复写的数据都会传播,而不只是变更。)合并式复写将在 第28章 详细说明。
复写资料
 
您必须将要复写的数据储存在一个称为发行集的对象中。一个 发行集(publication) 是由一个(含)以上的发行项组成。让我们更详细的看一下发行项与发行集。
发行项
 
之前已提到,一个发行项是要复写的数据的个别集合。一个发行项可以是一整个数据表,或是由特定的数据行与数据列构成的数据表子集,或是一个预存程序。您可以使用筛选器来建立子集。「水平筛选器(horizontal filter)」可用来建立由数据列构成的子集;「垂直筛选器(vertical filter)」则可用来建立由数据行构成的子集。水平与垂直筛选器将在本章稍后详细说明。
________________________________________
说明
在合并式复写中,筛选器的定义与运作跟快照式与交易式复写并不相同。本章与接下来的两章将会详细说明。
________________________________________
发行集
 
发行集是发行项的集合,这些发行项被组合在一起视为一基本单元。发行集将逻辑分组后的发行项视为一组复写对象。举例来说,您可以建立一个发行集来复写一个由许多数据表构成的数据库,每个数据表定义成一个发行项。在复写数据库时,以一个发行集来复写整个数据库会比数据表个别地复写要来得更有效率。
发行集可由单一的发行项来构成,但它多半都包含有一个以上的发行项。不过,订阅者只能订阅发行集,而不能订阅发行项。因此,如果您希望订阅一个单一的发行项,您必须设定一个只有此发行项的发行集,然后订阅这个发行集。
发送与提取订阅
 
复写资料可以利用数种方法来传送。所有的传送方法的基础不是「发送订阅」(push subscriptions)便是「提取订阅」(pull subscriptions)。订阅者可以支持同时混合了发送订阅和提取订阅的订阅方式。
发送订阅
 
当使用发送订阅时,散发者负责为订阅者提供更新。更新的初始化并不需要任何来自订阅者的请求。发送订阅在需要集中管理时很有用,这是因为这些复写都由散发者控制和管理,而不是不同的订阅者。换言之,复写的初始化与排程由散发者掌控。
发送订阅允许您在复写排程上有更大的弹性。发送订阅可以被设定为保持复写情形接近实时同步,或根据规定的排程来执行更新。在本章的 〈规划复写〉 一节中,您将学到更多有关这些选项的内容。
提取订阅
 
提取订阅(pull subscription)允许订阅者初始复写,复写可依排程或以手动进行。提取订阅适用于当发行集拥有大量的订阅者或是订阅者联机时间不定。透过提取订阅,订阅者可定期联机网络及提取复写数据。提取订阅的另一个好处是可降低送至散发者的联机错误讯息。如果散发者欲初始复写至没有响应的订阅者,将产生错误讯息。因此,如果复写是由订阅者在联机时初始化,就不会产生错误讯息。
复写代理程序
 
数个代理程序可执行将复写数据由发行者传至散发者,到最后至订阅者手中。这些代理程序包括:快照集代理程序、记录读取器代理程序、散发代理程序、合并代理程序及队列读取器代理程序。本节将学习如何管理这些代理程序。
快照集代理程序
 
「快照集代理程序」用于建立及传播快照集至散发者(或快照点)。快照集代理程序建立复写数据(即快照集)和建立信息,此信息可让散发者代理程序用来传播数据(此信息即中继数据)。快照集代理程序将数据快照储存至散发者,或指定其它或者额外位置来储存。快照集代理程序也负责维护复写对象的同步状态信息;这项信息储存在发行者数据库中。
快照集代理程序依排程的不同,可定时启动执行作业。快照集代理程序会执行下列步骤:
1. 建立散发者与发行者之间的联机。假设两者未联机,则快照集代理程序不会建立快照集。当联机建立,快照集代理程序则锁定所有发行项,以确保数据快照集的一致性。(由于锁定后可以防止其它使用者更新数据表,因此快照集代理程序必须安排在数据库活动的离峰时间执行。)
2. 建立发行者与散发者之间的联机,并为每个发行项写入一份数据表结构描述至散发者数据库,这份数据即为中继数据。
3. 复制发行者上已经发行数据表中的数据,将其写至快照集资料夹中。快照集数据夹不一定要放在散发者。如果所有订阅者均属于 SQL Server 系统,则快照集会储存为 原生大量复制工具程序(native bulk copy program) (大量复制在 第24章 有讨论)档案。若有一或多个订阅者属于异质性数据来源,则快照集会储存成文字文件。至此由快照集代理程序设定同步信息。
4. 当数据被复制后,快照集代理程序即更新于散发者数据库信息。
5. 释放每一个已经发行数据表的共享锁定,并完成记录历程数据表的写入动作。
所以,快照集代理程序仅负责建立快照集,而散发数据至订阅者则由其它代理程序执行。
当使用快照集复写且在发行者的数据有异动,快照集应经常更新。由于快照集固定被复制至订阅者,故应保持最新状态。
________________________________________
说明
当使用的是交易式复写或合并式复写,或是增加新订阅,就无须更新快照集。
________________________________________
记录读取代理程序
 
记录读取代理程序用于交易式复写。它可将标示为复写的交易,自发行者的交易记录移至散发数据库中。标示为交易式复写的每个数据库都具有一个在散发者的记录读取器代理程序。记录读取器代理程序会在本书 第27章 详细讨论。
散发代理程序
 
散发代理程序(Distribution Agent)散发快照集与来自散发者数据库中的交易至订阅者。每一个发行者均有自己的散发代理程序。如果使用发送订阅,则透过散发者的散发代理程序执行。如果使用提取订阅,则透过订阅者的散发代理程序执行。
合并代理程序
 
合并代理程序(Merger Agent)可搭配合并式复写,用在合并递增数据。当使用合并式复写,就不使用到散发代理程序或快照集代理程序,而是使用合并代理程序连结发行者和订阅者。在 第28章 我们会详细讨论合并代理程序。
队列读取器代理程序
 
队列读取器代理程序(Queue Reader Agent)用来传送更新数据至具队列更新选项的快照式复写或交易式复写订阅者。这个选项允许在不使用分布式交易的情况下,在订阅者处作变更。
监视复写代理程序活动
 
您可使用 Enterprise Manager 监视复写代理,步骤如下:
1. 在 Enterprise Manger 中展开服务器群组,然后展开指定为散发者数据库的服务器。
2. 在 复写监视器 按一下鼠标右键,然后按一下 效能监视器 。
3. 展开 复写监视器 数据夹,然后展开 代理程序 数据夹。
4. 展开欲监视的代理程序数据夹。
5. 按一下要监视的代理程序,在右方详细数据窗格的数据列按一下鼠标右钮叫出快捷菜单,然后按一下 代理程序历程 即可监视复写代理程序历程。
设定发行与散发
 
要设定发行与散发,可透过 设定散发暨发行精灵(Configure Publishing and Distribution Wizard) ,也可透过预存程序设定发行与散发,但透过 设定散发暨发行精灵 是较建议的做法。透过 Enterprise Manager,可利用以下的精灵作复写设定:
•  建立发行集精灵
 
•  建立提取订阅精灵
 
•  建立发送订阅精灵
 
•  停用发行和散发精灵
 
本节将介绍的设定发行与散发程序适用所有复写类型。在设定发行与散发者后,再设定复写类型(本章稍后及以下两章会介绍如何设定各类型复写)。以下为设定发行与散发程序:
1. 在 SQL Server Enterprise Manager,按一下设定为散发者的服务器。从 工具列 选择 精灵 。在 选择精灵 对话框显示后,展开 复写 资料夹,选择 设定散发暨发行精灵 ,如图 26-1。按 确定 。
 
 
图26-1 「选择精灵」对话框
2. 出现 设定散发暨发行精灵 欢迎画面,如图 26-2。
 
 
图26-2 「设定散发暨发行精灵」欢迎画面
3. 按 下一步 以显示 选取散发者 画面,如图 26-3。
 
 
图26-3 「选取散发者」画面
4. 在这个画面里您可以选择将我们在步骤一选取的服务器设为散发者及发行者,或是仅设定发行者并使用一个先前已完成设定的散发者。如果您选择设定最近的系统作为散发者,按一下第一个选项。精灵将会为您建立散发数据库与记录文件。如果您想要使用另外一个系统作为散发者,按一下第二个选项。如果没有其它的 SQL Server 系统被设定成散发者,则可用的选项将只有第一个。以一个专用的系统来作为散发者会是比较适合的选择。
________________________________________
说明
一个发行者只能定义一个散发者,所有的发行集应使用同一个散发者。
________________________________________
5. 如果您选择使用另一个系统作为散发者,您必须注册该 SQL Server 系统并且它必须已被设定为散发者。按一下「新增服务器」按钮,并在「注册 SQL Server 属性」窗口中选择一种验证方式来建立散发者上 SQL Sever 的联机。
6. 在范例中,选择设定中的系统为散发者。
7. 现在,精灵会确认发行者已经可以存取散发者。若是登入程序失败, SQL Server 代理程序属性 窗口会出现,允许修改代理程序注册账号,如图 26-4 所示。
 
 
图26-4 「SQL Server 代理程序属性」窗口
________________________________________
说明
如果在设定 SQL Server时使用本机系统账号,会看到这种讯息:本机系统账号仅具本机系统权限;故名。如果在设定 SQL Server 时使用网域账号,就不会出现步骤七的 SQL Server 代理程序属性窗口。
________________________________________
8. 在这个窗口中,可以修改 SQL Server 代理程序的其它功能(相关信息可参照 第31章 )。完成设定后按依下 确定 。
9.  设定 SQL Server 代理程序 画面出现,如图 26-5 所示。这个画面提示将 SQL Server 代理程序设为自动启动。复写将依 SQL Server 代理程序命令执行。所以若代理程序不执行,复写也将无发执行。建议选择让 SQL Server 代理程序自动启动,按一下 下一步 。
 
 
图26-5 「设定 SQL Sever 代理程序」画面
10.  指定快照集数据夹 画面出现,如图 26-6 所示。指定快照集位置,可以使用预设位置或指定新位置。按 下一步 继续。
 
 
图26-6 「指定快照集数据夹」画面
11.  自订组态 画面出现,如图 26-7 所示。
 
 
图26-7 「自订组态」画面
12. 在这个画面,可选择皆预设(第 2 个选项)或自订散发者数据库。如选择接受预设,安装过程即完成并出现完成画面。在这里,我们先选择第 1 个选项继续设定。
________________________________________
说明
预设的位置可能会选择到空间不够大的磁盘,因此我们继续设定步骤,学习如何自订散发者数据库。
________________________________________
13. 选择 下一步 进入 提供散发者数据库信息 画面,如图 26-8 所示。指定散发数据库名称及档案与记录文件位置。
 
 
图26-8 「提供散发者数据库讯息」画面
14. 按 下一步 进入 启用发行者 画面,如图 26-9 所示。选择一个与步骤一不同的发行者,或新增一个发行者数据库(按 新增 即可新增一个联机至 SQL Server 的发行者)。
 
 
图26-9 「启用发行者」画面
15. 按 下一步 进入 启用发行集数据库 画面,如图 26-10。可针对单一数据库选择启用交易式或合并式复写,预设状态下不会选取任何复写类型,因此如略过这个步骤,会建立一个发行者和散发者,但不会定义发行集。发行集可透过 建立发行集精灵 设定(较为建议的做法)。
 
 
图26-10 「启用发行集数据库」画面
16. 按 下一步 进入 启用订阅者 画面,如图 26-11 所示。选择订阅这个发行集的订阅者。我们建议不要使用这个步骤来选择,最好是透过 设定发行暨发行集精灵 来做这项设定。
17. 按 下一步 进入 完成散发暨散发精灵的设定 画面,如图 26-12 所示。这个画面会显示设定摘要。按 完成 完成设定,会花一点时间建立设定。当设定完成,会列出设定进行的程序,及是否需要设定 SQL Server 代理程序为自动启动。要在 SQL Server 代理程序执行的情况下,复写代理程序才会执行。当设定程序完成,就可看到在 Enterprise Manager 内多了 复写监视器 。
 
 
图26-11 「启用订阅者」画面
________________________________________
说明
如果想要变更复写数据库的设定,在 Enterprise Manager 内点选该数据库,在 工具 选择 复写 ,从列出的项目中选取预更改的选项。
________________________________________

 
 
图26-12 「完成散发暨散发精灵的设定」画面
快照式复写
 
本节提供快照式复写的详细信息。首先学习何时使用快照式复写。接着介绍规划快照式复写。
使用快照式复写
 
快照式复写在数据大多属于静态数据且不常变更的情况下适用。如同之前所学,快照式复写即将数据产生快照集并传送至订阅者。数据将会在下一次快照集使用时更新。如果使用快照式复写,由于在下次使用快照集时就会更新,因此不需修改在订阅者上的数据。
适合使用快照式复写的时机如下:
•  某个销售单位散发产品价格表至所有旗舰店,所有价格每晚更新一次。
 
•  检视数据表,该数据表不需经常更新,属于静态数据。
 
当数据需要经常性的更新(经常需要复写),交易式或合并式复写则较为适用。
设定快照式复写
 
如之前所提到,设定任何复写型态前,需设定发行者与发行集(如本章之前所示)。要设定快照式复写,要先设定发行集,然后设定订阅者。
设定发行集
 
设定发行集可指定欲复写的数据,复写的方式,及何时产生复写。设定步骤如下:
1. 使用 Enterprise Manager,透过下列任一步骤执行设定,选择 工具 / 复写 ,点选 建立和管理发行集 ,或是选择 工具 / 精灵 ,选择 建立发行集精灵 。用任一方式都可进入建立和管理发行集的对话框,如图 26-13 所示。这里可选择预发行的数据库或数据表。
 
 
图26-13 「建立和管理发行集」对话框
若发行集已存在,下列的按键就会显示:
o  发送新的订阅 :可为已建立发行集建立新的发送订阅,这个步骤将会在本章 〈设定订阅集〉 一节讨论。
 
o  属性与订阅 :可更改发行集与订阅集属性。
 
o  指令化发行集 :可建立指令用以建立更多发行集。
 
o  删除发行集 :可删除已设定的发行集。
 
2. 选择发行集数据库(如图 26-13,选择 Northwind 为发行集数据库),选择 建立发行集 进入 建立发行集精灵 的欢迎画面,如图 26-14 所示。
 
 
图26-14 「建立发行集精灵」的欢迎画面
3. 注意在这个窗口,下方有 显示这个精灵中的进阶选项 选项。我们先不勾选这个选项,因为如果勾选这个选项,就会显示立即建立更新及队列更新订阅者选项。进阶选项允许订阅者更新发行集与发行者。此外,还会出现允许订阅集数据转换的选项。
点选 下一步 进入 选择发行集的数据库 窗口,如图 26-15 所示。可再次选择欲发行的数据。在步骤二选取的数据库会被点选。

 
 
图26-15 「选择发行集的数据库」画面
4. 选择 下一步 进入 选取发行集类型 窗口,如图 26-16 所示。
 
 
图26-16 「选取发行集」窗口
可选择任一复写类型,三种发行集的功能如下:
o  快照式发行集 :可定期复制发行项的快照集至订阅者。可在任一数据表上建立快照式发行集。
 
o  交易式发行集 :可建立交易式复写,在发行集数据发生修改时,将交易撷取并传至 订阅者 。只有当数据表设有主索引键时,发行项才可被建立。
 
o  合并式发行集 :可允许发行者与订阅者双向复写。任一数据表都可建立发行项。
 
5. 选择 快照式发行集 ,按 下一步 进入 指定订阅者类型 窗口,如图 26-17 所示。这个窗口可以指定是否所有的订阅者执行 SQL Server。图 26-17 显示预设情况下的选择,预设的设定指定所有的订阅者都执行 SQL Server 2000。如果接受此设定,就是将复写设定为使用原始 SQL Server 2000 的数据类型。其它还可以选择 SQL Server 7.0 的服务器,或其它性质的服务器,这个选项会使复写数据转换回字符格式,当然也会经过一些繁杂的转换手续。
 
 
图26-17 「指定订阅者类型」画面
6. 按 下一步 进入 指定发行项 画面,如图 26-18 所示。在这个画面,可以指定将数据表或其它数据库对象当作发行项来复写。这些发行项构成您所建立的发行集。在左手边所列出的画面,可以在 显示 中复选所列出的项目,包括 数据表 、 预存程序 及 检视表 ,一但勾选任何一个项目,在右手边的窗口就会列出这些项目的数据表明细。然后您可以在右手边的明细中再勾选想要发行的数据表,或是回到左手边的窗口,勾选 全部发行 选取项目中的所有数据表。记住,每一个数据表、预存程序或检视表都是一个独立的发行项,而发行集是由一组发行项构成。
注意在此画面中的发行项默认值按钮。这个按钮允许在系统中不同的发行项设定默认值,当按下这个按钮,会出现发行项的类型供您选择。选择数据表发行项后按确定,会进入预设数据表发行项属性窗口,如图 26-19 所示。一般卷标页中可指定下列的选项:
o 发行项名称
 
o 发行项描述
 
o 发行项的来源资料表名称
 
o 发行项的来源资料表拥有者
 

 
 
图26-18 「指定发行项」画面

 
 
图26-19 「预设数据表发行项属性」窗口的「一般」卷标页
在 快照集 标签页中,如图 26-20 所示,可设定以下选项:
o 卸除任何现有数据,并指定如何操作索引。
 
o 指定是否是否复制丛集索引或非丛集索引。
 
o 指定是否将使用者自定数据型别转换为基底数据型别。
 
o 指定是否复制条件约束。
 
指定设定后按 确定 。

 
 
图26-20 「预设数据表发行项属性」窗口的「快照集」标签页
7. 确定 指定发行项 的选项后按 下一步 ,进入 发行项的问题 窗口,一个发行集的分析窗口就建立了。如果要发行的是 Northwind 数据库,如图 26-21 所示,会提醒您当 IDENTITY 数据行被传到订阅者时,并不会传送 IDENTITY 属性。
8. 在分析了发行集之后,按 下一步 进入 选取发行集名称与描述 窗口,如图 26-22 所示。在这个画面中,可以简单的指定发行集名称和描述,也可以在 Active Directory 服务中选择列出这个发行集。
 
 
图26-21 欲复制 IDENTITY 数据行时出现的窗口

 
 
图26-22 选取发行集名称与描述
9. 按 下一步 进入 自定发行集的属性 窗口,如图 26-23 所示。在这个画面中,可以指定是否定义资料条件筛选(选择 是 即可),或是使用预设的设定选项(选择 否 )。若是选择 否 后按 下一步 ,就后完成建立发行集精灵,如图 26-31(在本节快要结束的地方)。本例中,我们先选择 是 来看看剩下的画面还提供哪些选项的设定。
 
 
图26-23 「自定发行集的属性」画面
10. 选择 下一步 进入 筛选数据 画面,如图 26-24 所示。在这个画面中,可以指定要垂直筛选还是水平筛选数据行(也可以两个都选择)。本例中,我们两项都勾选。
________________________________________
说明
不论使用的是快照式或交易式复写,条件筛选所提供的功能皆相同。但是,条件筛选的执行方式就和所使用的复写类型有关。在下一章中,我们会学习条件筛选对交易式复写的影响。在快照式复写中,是用建立快照集的 WHERE 子句来进行筛选的动作。本节步骤十三会解释如何指定 WHERE 子句。
________________________________________
11. 按 下一步 进入 筛选数据表的数据行 画面,如 26-25 所示。这个画面可以排除不要复写的数据行。首先从 发行集中的数据表 内点选 数据表 ,然后在 选取数据表中的数据行 内将不要复写的资料行的复选框取消。这样就允许将发行项垂直筛选,也就是相较于发行者的数据表,复写的资料表上会有较少的资料行。
 
 
图26-24 「筛选资料」画面
________________________________________
说明
主索引键数据行不能被排除,下一章会解释不能被排除的原因。
________________________________________

 
 
图26-25 「筛选数据表的数据行」画面
12. 按 下一步 进入 筛选数据表的数据列 画面,如图 26-26 所示。这个画面可选择排除不想要的数据列。选取一个数据表后按下 [...] 按钮,建立筛选。
 
 
图26-26 「筛选数据表的数据列」画面
13.  指定筛选 对话框出现,如图 26-27 所示。这个对话框允许在 SQL 陈述式中加入 WHERE 子句,排除必要的数据列。当完成所要排除的数据列时,按 确定 回到设定精灵。
 
 
图26-27 「指定筛选」对话框
14. 按 下一步 进入 允许匿名订阅 画面,如图 26-28 所示。这个画面允许指定是否允许匿名订阅或具名订阅。可依您实际需要选择。
 
 
图26-28 「允许匿名订阅」画面
15. 按 下一步 进入 设定快照集代理程序的排程 ,如图 26-29 所示。在这个画面您可接受预设的排程设定,或是按 变更 按钮进入编辑排程的对话框。
 
 
图26-29 「设定快照集代理程序的排程」画面
16. 按 变更 进入 编辑重复执行作业排程 对话框,如图 26-30 所示。这个对话框可指定快照集发行的排程,选择适合您需求的设定。图 26-30 显示该快照集的开始时间和结束时间为同一天。如果在设定的是快照式复写(如现在正在操作中的程序),且要快照集定时更新,就要将快照集排程设为循环的排程。当设定的是交易式复写,就要在建立新的订阅者后再执行快照集(除非之前设定的是匿名订阅者)。合并式复写会将最新的快照集送至订阅者,因此,在设定合并式复写时,可以在将要建立或建立新的订阅者后马上执行快照集。设定完成后按 确定 。
 
 
图26-30 「编辑重复执行作业排程」对话框
17. 按 下一步 进入 完成建立发行精灵 画面,如图 26-31 所示。这里可以看到所设定发行集的总结。
18. 检示总结信息后,按 完成 ,就可看到精灵建立发行集的过程,完成后会看到如图 26-32 的画面,告知发行集已成功的建立。
 
 
图26-31 「完成建立发行精灵」画面

 
 
图26-32 告知发行集成功建立画面
现在发行集已成功建立,并可发行至订阅者处。您可以在 建立与管理发行集 的对话框(本节稍早有提及),让订阅者开始运作,或是修改这个发行集的属性。
修改快照集排程
 
当网络状况变更,可能会需要修改快照集的排程(启用快照集排程设定的步骤在本节稍早做过介绍),当设定快照式复写排程,必须考虑下列几项因素:
•   资料的变动性 :如果数据经常更新,快照集就必须经常更新,反之亦同。
 
•   更新的必要性 :订阅的系统是否取决于数据的更新?如果答案是肯定的,快照集就必须经常更新。
 
•   系统的执行速度 :如果网络、发行者、散发者和订阅者的系统速度都很快,就算快照集的更新频率较高,也不会影响系统中其它组件的执行效能。
 
依照以下的步骤设定快照集排程:
1. 在 Enterprise Manager,展开想要修改的服务器,展开 复写监视器 数据夹,展开 代理程序 后,选择 快照集代理程序 数据夹。
2. 在右手边的窗格中,点选欲修改的发行集按下鼠标右钮,叫出快捷菜单后选择 代理程序属性 ,如图 26-33 所示。
 
 
图26-33 Enterprise Manager 中的一个发行集
3. 进入 属性 窗口,如图 26-34 所示。这个窗口显示发行集代理程序可选择的属性。
 
 
图26-34 「代理程序属性」窗口的「一般」卷标页
4. 在这个画面中选择 排程 标签页,如图 26-35 所示。在此标签页中可以检视现存的发行集排程。 新的排程 按钮允许新增排程,而 新的警示 按钮则允许新增警示。 编辑 按钮可用来修改已存在的排程,而 删除 按钮用来删除已存排程。
 
 
图26-35 「代理程序属性」窗口的「排程」标签页
5. 选择 编辑 进入 编辑作业排程 对话框,如图 26-36 所示。这个对话框允许将快照集代理程序设定符合需求的排程。在点选 重复执行 时按下 变更 按钮,进入 编辑重复执行作业排程 对话框。可以设定在当 CPU 休息时才执行代理程序。这样的设定在某些状况下有其优点,不过一但设定这个选项,您就无法预期代理程序会在何时执行。输入合适的排程后按 确定 按钮。
 
 
图26-36 「编辑作业排程」对话框
当完成上述步骤,发行者会在发行者数据库中更新快照集的信息。这个排程会决定快照集建立的频率。若是想要更新快照集复制到订阅者的频率,必须为订阅设定发行集代理程序。
启用订阅者
 
在设定订阅者前,必须在发行集数据库中启用订阅者。启用订阅者可以让 SQL Server 系统和发行集数据库沟通。在建立了发行集数据库和订阅者间的联机后,就可以设定订阅者(这个过程会在下一节 〈设定订阅者〉 解释)。现在先参照以下步骤启用订阅者:
1. 在 Enterprise Manager,选择 工具 菜单。选择 复写 / 设定发行、订阅及散发者 ,或是在选择 工具 菜单中直接选择 精灵 / 复写 / 设定散发暨散发精灵 ,进入 发行者和散发者属性 窗口,如图 26-37 所示。
2. 发行者和发行者属性窗口,选择 订阅者 标签页,如图 26-38 所示。本卷标页中可以看到在网络上已定义的订阅者清单。订阅者必须已定义在清单中才可接收订阅。
 
 
图26-37 「发行者和散发者属性」窗口
这个标签页中可以指定,哪些订阅者对标签页中列出的发行者有订阅权限。在第一次开启 发行者和散发者属性 窗口时,由于还没有新增任何订阅者,因此窗口中仅列出发行者系统。

 
 
图26-38 「发行者和散发者属性」窗口的「订阅者」标签页
3. 欲新增订阅者,先按下 新增 按钮进入 启用新的订阅者 对话框,如图 26-39 所示。在此对话框中,选择想要启用的订阅者(SQL Server、Microsoft Access、OLE DB、ODBC等)。这里的设定决定新订阅者所订阅的发行集类型。选择 SQL Server Database 后按下 确定 。
 
 
图26-39 「启用新的订阅者」对话框
4. 现在会进入 注册的 SQL Server 属性 窗口,如图 26-40 所示。由于在前一个步骤选择的是 SQL Server 数据库,因此在这个窗口所出现的选项都和 SQL Server 联机的选项有关。如果在前一个步骤中选择的是其它的选项,则会出现不同的窗口。可指定订阅者的系统名称和账户认证模式。
 
 
图26-40 「注册的 SQL Server 属性」窗口
如果想选取更多的 SQL Server 系统,按下在服务器旁的 [...] 按钮,可进入选择服务器对话框,如图 26-41 所示。在这里可以选择想要设为订阅者的服务器。

 
 
图26-41 「选择服务器」对话框
5. 步骤四的设定完成后按下 确定 ,并在 注册的 SQL Server 属性 窗口中也按下 确定 , 发行者和散发者属性 窗口会再出现,并且在 订阅者 的清单中会出现上个步骤中新增加的订阅者,如图 26-42 所示。新增后的系统就可以当作所指定发行者的订阅者。
 
 
图26-42 显示新订阅者的「发行者和散发者属性」窗口
设定订阅集
 
在设定了发行者、散发者和发行集,以及启用订阅者后,就可开始设定订阅。可以设定订阅是来自订阅者或是发行者。如果是来自订阅者,则可设定提取订阅;如果是来自发行者,则可设定发送订阅。
设定提取订阅
 
提取订阅的设定及管理在订阅者端,因此,在开始 提取订阅精灵 前要在 Enterprise Manager 选择订阅者系统。通常,订阅者并非经常联机到网络使用提取订阅。举例来说,业务人员可设定提取订阅,每次当使用笔记型计算机时才联机更新订阅。参照以下步骤设定提取订阅:
1. 在 Enterprise Manager 选择 工具 / 复写 / 提取订阅至 ,在 提取订阅至 对话框中选择 提取新的订阅 ,或是在 工具 中选择 精灵 / 复写 / 提取定于精灵 。任何一种方式都可以进入 欢迎使用提取订阅精灵 ,如图 26-43 所示。
 
 
图26-43 「使用提取订阅精灵」的欢迎画面
2. 选择 下一步 进入 寻找发行集 画面,如图 26-44 所示。这里可以选择寻找发行者的方式,可以是透过注册服务器(默认值),或是在 Activity Directory 中寻找。这里可以决定如何搜寻发行者,这里的决定影响下一个画面呈现的结果。
 
 
图26-44 「寻找发行集」画面
3. 按 下一步 进入 选取发行集 画面,如图 26-45 所示。这里可以看到有哪些会被应用在复写的发行集。注册在 SQL Server 系统上的服务器在这里都会列出。展开所选的发行者系统,并选择要使用的发行集,如图 26-45 所示。
如果需要注册一个服务器,按 注册服务器 进入 注册服务器属性 窗口。在上一节中启用订阅者时我们曾经使用此窗口。
4. 选取发行集后按 下一步 进入 指定同步代理程序登入 面,如图 26-46 所示。这里可以指定代理程序联机到发行者时的方式和登入账号。默认值选项是 仿真 SQL Server 代理程序账户 ,这通常也是较理想的选项。如果设定系统中的 SQL Server 代理程序使用特别的登入,就必须在这里指定。
 
 
图26-45 「选取发行集」画面

 
 
图26-46 「指定同步代理程序登入」画面
5. 选择 下一步 进入 选取目的数据库 画面,如图 26-47 所示,这里可以指定复写的发行项要放在哪个数据库中。图 26-47 显示我们为订阅集选取了pubs数据库。如果要建立新的数据库,按 新增 进入 数据库属性 窗口。
 
 
图26-47 「选取目的数据库」画面
6. 如果开启了 数据库属性 窗口新增数据库,新增完成后按 确定 就可回到 选取目的数据库 窗口。然后再按 下一步 进入 初始化订阅 画面,如图 26-48 所示。选择 是,初始化结构描述与数据 来开始订阅者端的数据库结构和数据。
 
 
图26-48 「初始化订阅」画面
7. 按 下一步 进入 快照集传送 画面,如图 26-49 所示。这里可以选择快照集从哪里传送。通常接受默认值的位置即可。
 
 
图26-49 快照集传送画面
8. 按 下一步 进入 设定散发代理程序排程 画面,如图 26-50 所示。这个画面可以选择连续更新、依排程更新、或是仅在需要时更新。
记住本例中我们所设定的是快照式复写,所以当更新产生,所有的发行项内容都会更新至订阅者端。这里的选项可依您数据更新的频率,以及保持数据同步的必要性来决定。按下 变更 按钮可以进入 编辑重复执行作业排程 对话框(本章之前有提及),这里可以自订重复执行作业的排程。
9. 按 下一步 进入 启动必要的服务 画面,如图 26-51 所示。如果 SQL Server 代理程序还未被启动,从这个画面中可以启动服务。这里可以看到 SQL Server 代理程序是否已在订阅者端启动。若是还未被启动,会提示您启动该代理程序,若是想手动启动代理程序,在Enterprise Manager 中展开 管理 数据夹,在 SQL Server 代理程序中按下鼠标右钮,在快捷菜单中选择启动或停止 SQL Server 代理程序即可。
 
 
图26-50 「设定散发代理程序排程」画面

 
 
图26-51 「启动必要的服务」画面
10. 如果 SQL Server 代理程序未被设为自动启动,就会看到 设定 SQL Server 代理程序 画面,按下 确定 即可。如果 SQL Server 代理程序已设为自动启动,就不会看到这个画面。
11. 按 下一步 进入 完成提取订阅精灵 画面,如图 26-52 所示。选择 完成 即可完成订阅集的设定作业。
 
 
图26-52 「完成提取订阅精灵」画面
现在发行项会依设定的排程,在订阅者端被复写。在确认发行集代理程序的排程后,再启用复写。如果没有设定及时产生快照集至散发者端,在快照集代理程序依自己排程执行的情况下,可能需要一些时间才能将数据送至散发者端。就算复写在执行中,实际的数据也会在快照集代理程序作业完成后才会送至订阅者端。
设定发送订阅
 
发送订阅要在发行者端启动,可使用 发送订阅精灵 来设定。当使用发送订阅,复写的排程由发行者端决定。发送订阅适用于联机固定的订阅者。使用这类型订阅集的目的是在散发者端就可以方便的管理所有的订阅集,不需要在订阅者端个别的管理每一个订阅集。请参照以下步骤使用 发送订阅精灵 :
1. 使用以下任一方法进入 发送订阅精灵 。第一种方法是在 Enterprise Manager 中点选 工具 ,选择 复写 / 将订阅发送至其它服务器 ,进入 建立与管理服务器的发行集 对话框,如图 26-53 所示。然后选择 发送新的订阅 。
 
 
图26-53 「建立与管理服务器的发行集」对话框
或是使用第二种方法,在 工具 中选择 精灵 ,在 选择精灵 对话框中展开 复写 ,选择 建立发送订阅精灵 ,然后按下 发送新的订阅 ,任何一种发法都可以进入 欢迎使用发送订阅精灵 画面,如图 26-54 所示。

 
 
图26-54 「欢迎使用发送订阅精灵」画面
2. 按 下一步 进入 选择订阅者 画面,如图 26-55 所示。这里可以指定发行集要发送至哪一个订阅者端。本例中,我们选择的系统是 B6S8A9。这些订阅者必须被启用,如稍早 〈启用订阅者〉 一节所示范。
 
 
图26-55 「选择订阅者」画面
3. 选择 下一步 进入 选取目的数据库 画面,如图 26-56 所示。这里可以指定订阅者端的数据库,可以选择已存在的数据库,或是建立新的数据库。输入所要的数据库名称,或按 浏览或建立 按钮后从清单中挑选。要建立新的数据库,在按下 浏览或建立 按钮后选择 建立新对象 ,就可进入 数据库属性 窗口设定。当完成建立新数据库后,按下 确定 就可回再到 选取目的数据库 画面。
 
 
图26-56 「选择订阅者」画面
4. 按 下一步 进入 设定散发代理程序排程 画面,如图 26-57 所示。在这里可以选择连续更新订阅集或选择依排程更新订阅集。以快照式复写来说,选择连续更新并不合理。如果要变更排程,按下 变更 按钮进入之前所解释过的 编辑重复执行作业排程 对话框,更改排程。
 
 
图26-57 「设定散发代理程序排程」画面
________________________________________
说明
精灵中设定的排程是用来更新快照集客户端的排程,和更新快照集的排程必须要协调。如果快照集本身没有更新,传送到客户端的的数据就是旧的快照集数据。
________________________________________
5. 按 下一步 进入 初始化订阅 画面,如图 26-58 所示。在这里可以指定订阅集是否开始。初始化结构描述和在订阅者端的数据集已由预设指定。如果结构已存在, 否,订阅者已经有结构描述和数据 这个选项就不会提供选择。这个画面中也可以启动快照集代理程序。建议在开始快照集时就启动快照集代理程序,否则就必须手动启动代理程序。设定快照集代理程序排程,使其和发送订阅的排程具一致性也很重要,可参照本章在 〈修改快照集排程〉 一节的叙述。
 
 
图26-58 「初始化订阅」画面
6. 按 下一步 进入 启动必要的服务 画面,如稍早的图 26-51 所示,可指定用自动启动的方式启动 SQL Server 代理程序。
7. 按 下一步 进入 完成发送订阅精灵 画面,如图 26-59 所示。检查设定是否正确,按 完成 开始将快照集复制到订阅者的程序。您会看到一个描述程序进行的对话框,最后会出现操作程序完成的消息框。当精灵完成后,发送订阅就建立,且会定期更新。
 
 
图26-59 「完成发送订阅精灵」画面
管理复写
 
在学习了 SQL Server 2000 环境中设定及安装复写数据库后,可以利用 Enterprise Manger 中的监控功能,管理复写环境或找出任何使复写无法运作的问题。
复写代理程序的监控与管理
 
在 Enterprise Manager 中的 复写监视器 数据夹可以找到 代理程序 。请参照以下步骤存取代理程序:
1. 展开服务器群组、您的服务器、及复写监视器数据夹。
2. 如果展开的是发行者端服务器, 发行者 和 代理程序 数据夹会出现在 复写监视器 内。 发行者 数据夹内包含属于此服务器的所有发行者。 代理程序 数据夹内含有 快照集代理程序 、 散发代理程序 、 合并代理程序 ,及用来清除历史登入数据的 其它代理程序 。
3. 虽然代理程序通常不需要被启动或停止,但需要时可使用 复写监视器 来执行。如果复写系统并未依设定执行,很可能是因为没有启动快照集代理程序。(这就是为什么之前在设定过程中我们建议选择立刻执行初始快照集)。在 Enterprise Manager 中按下一个代理程序的数据夹,检查代理程序的状态,并在右方窗格中检示有关代理程序的的的信息,如图 26-60 所示。这里可以决定是否执行某个代理程序,也可以看到是否该代理程序正在使用中。当启动了某个代理程序,代理程序会执行直到任务完成,然后停止作业。接者,SQL Server 代理程序会依排程复写代理程序。
 
 
图26-60 在Enterprise Manager 中的快照集代理程序
4. 在代理程序中按下鼠标右钮叫出快选菜单,在这里有几个可以提供监视和管理代理程序的选项,如图 26-61 所示。
 
 
图26-61 复写代理程序选项
这些选项的简介如下:
o  错误详细数据 :列出任何曾发生的错误清单。
 
o  代理程序历程记录 :列出代理程序活动。
 
o  代理程序属性 :可修改复写代理程序的排程,数据库存取方式,代理程序的步骤,以及作业完成后的执行动作,如可选择以电子邮件通知代理程序所执行事件的完成。
 
o  代理程序设定文件 :可检视及修改代理程序参数,如登入逾时断线时间、批次大小、及查询逾时断线时间的设定等。
 
o  启动代理程序与停止代理程序 :可以启动或停止代理程序。
 
o  重新整理速度和设定值 :可修改重新整理执行监控数据的频率。
 
o  选取字段 :可指定结果集中想要检视的数据行。
 
o  说明 :提供关于此窗口的说明信息。
 
________________________________________
说明
发行集代理程序的监控会在下两章讨论。
________________________________________
停用复写
 
利用 Enterprise Manager 可停用所有或部分的复写,只要在 Enterprise Manger 的复写精灵中移除选定的复写组件即可。本节会学习如何简单地执行这项作业。
移除发送订阅
 
在散发者系统中,使用Enterprise Manager的发送订阅精灵就可移除发送订阅。在启动发送订阅精灵后就会出现 建立与管理发行集 对话框,点选要删除的订阅后,按下右方 删除发行集 的按钮,出现提示方块,询问是否确认删除此订阅。按 是 即可移除订阅。
移除提取订阅
 
在订阅者系统中,使用 Enterprise Manager 的发送订阅精灵就可移除提取订阅。在启动提取订阅精灵后就会出现 建立与管理发行集 对话框,点选要删除的订阅后,按下右方 删除发行集 的按钮,出现提示方块,询问是否确认删除此订阅。按 是 即可移除订阅。
移除散发和发行
 
要移除散发和发行,必须开启 停用散发暨发行精灵 。在停用精灵的第一个画面,必须指定是否停用所有散发及发行,或仅移除发行。如果选择的是第一个选项,服务器上所有的发行集、订阅和散发者都会被移除。如果选择的是第二个选项(预设选项),就只有发行集会被移除。在选项决定后,会出现确认画面,按下 是 按钮后就会移除所选的复写组件。
快照式复写校调
 
本节中会学习如何设定及校调快照式复写系统至最佳化执行效能。快照式复写系统的设定与校调,比起交易式和合并式复写系统要来的简单。在交易式和合并式复写中,快照集在一开始时被传送到订阅者端,然后小型的数据量会不断的传送到这些系统中。然而在快照式复写中,所有的数据库都会重新整理,因此在操作上会简单的多。在本节中我们先讨论快照式复写的属性,然后再讨论其设定、监控及校调的重点。
快照式复写
 
由于快照式复写先将已存在的数据库复制散发者,然后到订阅者,因此快照式复写的执行效能取决于特定的系统组件是否有传送大量数据的能力。以下为影响快照式复写执行效能的几项因素,若是正确的指定快照集大小和系统设定,就可以降低这些因素对效能的影响。
•   发行者的 I/O 效能 :不论是整个数据库或是部分数据库都是从发行者端复制,因次发行者端 I/O 子系统的执行效能是其中一个影响快照式复写执行效能的因素。快照集的建立作业和 I/O 较有关系,通常和 CPU 较无关。
 
•   散发者的 I/O 效能 :散发者端会在同一时间接收及散发大量数据,因此散发者的 I/O 子系统不够快,就会影响快照集建立的效率。
 
•   订阅者的 I/O 效能 :散发者会试者在同一时间散发所有或部分的数据库到订阅者端。如果订阅者端 I/O 子系统的执行效能不够好,就会影响复写的执行。
 
•   发行者、散发者和订阅者间的网络频宽 :由于三者间的数据传输数据量很大,因此很容易就在网络上产生瓶颈。确认网络频宽足以负荷复写的执行。
 
设定快照式复写
 
本节会提供一些关于快照式复写设定的要点。由于快照式复写利用发行集数据库作关于复写程序的信息状态分类,而并非复写数据本身(在一个数据夹),因此通常不需要在散发者端校调 SQL Server。这些要点可帮助您将快照式复写系统以最佳化设定,设定要点如下:
•  在发行者、散发者和订阅者端设定足够的 I/O 容量
 
•  设定发行者,让快照集保存在发行者系统
 
•  将散发者和发行者设定在同一系统上
 
•  增加 BCP 执行绪数量
 
现在来仔细研究这些设定要点。
设定足够的 I/O 容量
 
如前所述,快照式复写在同一时间复制大量的数据,所以速度慢的磁盘子系统会降低整个程序的的速度。因此将特定的 I/O 子系统执行效能增加,就可提高复写程序效能。在一个含复写功能的系统中(如 SQL Server 系统),交易记录文件应该被放在自己的 RAID 1 磁盘区中以保护数据。而数据夹则放置在一个或数个 RAID 10 到 RAID 5 磁盘区中。使用哪一个 RAID 层级取决于所设定的是发行者、散发者,还是订阅者。
 设定发行者的 I/O 子系统 不论发行者端的数据夹使用的是 RAID 5 或是 RAID 10 磁盘区,都取决于数据在该磁盘区存取数据的读写比例。如 第5章 所提及,如果数据的写入超过 10% 以上,RAID 10 就比 RAID 5 适用。不论选择使用哪一个 RAID 层级,应该依 第5章 和 第6章 所提的方式,适当分配 I/O 子系统大小。
 设定散发者的 I/O 子系统 由于快照式复写将数据存在散发者而非 SQL Server 数据库中,所以必须确定快照集的位置有足够的 I/O 容量容纳大量的写入数据。所以,快照集的位置较适合放在 RAID 10 磁盘区。在本节稍后会看到,在某些情况下,将快照集存在散发者较有效率。
 设定订阅者的 I/O 子系统 将订阅者数据夹放在 RAID 10 磁盘区可以加强快照式复写的效能,这是因为订阅者端在快照式复写时所遇到大量的资料写入。
________________________________________
说明
当设定快照式复写的 I/O 子系统时,应该考虑快照集发行的大小。如果快照式复写所复制的数据量很小,放在任何 RAID 层级都很方便。
________________________________________
选择快照集位置
 
由于快照式复写将快照先复制到散发者,然后到订阅者,您可以设定将这个多余的步骤由复写中移除。散发者仍被使用,只是现在把快照设定储存在订阅者端。这样就可以避免多余的网络复制操作。请参照以下步骤设定散发者,让快照存放在发行者端:
1. 在散发者端,叫出 设定散发暨发行精灵 ,并选择 发行者 标签页,如图 26-62 所示。
 
 
图26-62 「发行者」标签页
2. 按 [...] 按钮,进入 发行者属性 窗口,如图 26-63 所示。
 
 
图26-63 「发行者属性」窗口
3. 在这个窗口中,可以设定快照集在系统内的位置。在设定前必须确定这个位置的 I/O 容量足以应付快照集对系统造成的负荷。
________________________________________
说明
当在散发者端设定快照集,也等于设定了所有的发行集位置,所以如果散发者端有不只一个发行者系统,就不能做这样的设定。
________________________________________
在同一个系统内设定散发者和发行者
 
如果所使用的复写类型只有快照式复写,就可以简单的将发行者和散发者设定在同一个系统上。由于这样的设定可以不必透过网络将快照集复制到散发者端,所以可以降低网络流量。但是,如果发行者的效能很重要,最好还是将快照集保留在散发者端,让散发者端处理散发的问题。
增加 BCP 执行绪
 
透过增加快照集程序所使用的 BCP 执行绪,可以增加复写效能,请参照以下步骤设定:
1. 在 Enterprise Manager 中展开 复写监视器 数据夹,展开 代理程序 数据夹,然后选择 快照集代理程序 数据夹。在右方的窗格中,点选选择的发行集后按下鼠标右钮,在快捷菜单中选择代理程序设定文件,进入对话框,如图 26-64 所示。
 
 
图26-64 「快照集代理程序设定文件」对话框
2. 按 新增设定文件 按钮,进入 复写代理程序设定文件的详细数据 对话框,以修改或新增设定文件,此对话框如图 26-65 所示。在这里更改 MaxBcpThreads 的参数。
 
 
图26-65 「复写代理程序设定文件的详细数据」对话框
3. 当设定完成后,将设定档命名后按下 确定 ,就可储存此设定档。然后在 快照集代理程序设定文件 的对话框中选择这个设定档即可。
监视快照集系统
 
您可以使用 Microsoft Windows 2000 效能监视器来监视快照集。当使用 SQL Server 复写时,会在效能监视器中加入几个对象。另外,有一些效能监视器的标准对象对于监视快照式复写也很有用。这些对象包括:
•   SQLServer:Replication Agents :计算现在系统中有几个不同类型的代理程序正在执行。
 
•   SQLServer:Replication Dist :提供关于散发者延迟时间的信息。
 
•   SQLServer:Replication Snapshot :提供关于快照式复写效能的信息。
 
•   PhysicalDisk :提供关于 I/O 活动的信息,有很多效能上的问题都和 I/O 有关,所以这项信息对快照式复写格外有用。
 
•   Processor :允许监视系统处理器。
 
•   System :提供关于整个系统的信息。
 
这些计数器可使您清楚的知道复写程序如何的执行,如果系统的设定和校调都很适当,快照集的执行过程就会非常的快。要使复写的执行最佳化,注意以下可能产生问题的地方:
•   I/O 效能瓶颈 :I/O 率是否太高?注意 I/O 每秒的执行及每一次 I/O 的执行所需秒数。
 
•   网络效能瓶颈 :这并不是一个容易发现的瓶颈,但可以试着将网络输送量(network throughput)和快照式复写所需的时间比对。
 
校调快照集系统
 
快照集系统校调方式通常用简单的设定即可。影响复写效能最明显的问题不外乎就是 I/O 和网络效能,您必须看看您的网络效能是否足以负荷复写的所需。现在看看以下的范例。
假设您有一个 5GB 的数据库。如果您用的是 10BaseT 网络,网络的最大频宽就是每秒 10Mbps,差不多是每秒 1 megabyte(MBps)。因此,一个 5-GB 的数据库就要花掉 5120 秒来传送,或者说要花 1.4 小时在这个网络上复制。计算方式如下:(5 GB * 1024 (MB/GB)) / 1 (MBps) = 5120 秒,换算为 1.4 小时。比较起来,一个 100BaseT 网络就只需要 8.3 分钟就可完成同样的复写程序。一个 Gigabit 以太网络需要 51 秒完成同样的动作,计算的结果整理在表 26-1 中:
表26-1 网络比较表
网络速度  执行一个 5-GB 数据库快照集所需时间
10BaseT 5120 秒
100BaseT 516 秒
Gigabit 以太网络 51 秒
所以网络对执行效能影响由此可见。要计算如范例中般的精确,首先要了解执行一次的复写到底需要多少的时间。如果复写的时间太久,可能真的在哪里遇到瓶颈,如 I/O、内存、磁盘等等。
本章总结
 
本章学到 SQL Server 三种复写类型:快照式复写、交易式复写和合并式复写。此外也学到了 SQL Server 复写的的发行及订阅模式,并学到如何设定快照式复写。在 第27章 和 第28章 中,会学习比较复杂的复写类型,也就是不断提及的交易式复写和合并式复写。




25. 组件服务及 Microsoft 分布式交易协调员
组件服务概述
Microsoft 分布式交易协调员
本章总结
本章将学习 Microsoft 分布式交易协调员(Microsoft Distributed Transaction Coordinator,MS DTC),这项功能允许一个数据库交易可以存取多个资料来源,并且还能确保数据的完整性。您在这一章会看到 MS DTC 有许多用途,很多类型的应用程序都必须用到 MS DTC 提供的服务。
MS DTC 是组件服务的一个部份。组件服务由 Microsoft Windows NT 服务衍生而来,是内建于 Windows 2000 产品与技术的集合。组件服务包含了 Component Object Model(COM)、Distributed COM(DCOM)、Microsoft Transaction Server、Microsoft Internet Information Server 及 Microsoft Message Queue Server。在 Windows 2000 组件服务中,COM 和 DCOM 的技术有了新的层级,所以称 COM+。COM+ 应用程序和其它的系统服务组成 Windows 2000 组件服务这个项目。在正式介绍 MS DTC 之前,我们会先简单介绍组件服务。
组件服务概述
 
 组件服务(Component Services) 是由数个不同的产品组合而成的工具,使用统一的 Microsoft 管理主控台(Microsoft Management Console,MMC)管理窗口。组件服务是主控台的一个嵌入式管理单元,服务内容包括:
•  COM+ 应用程序服务
 
•  MS DTC
 
•  事件检视器服务
 
•  系统服务
 
•  Microsoft 讯息队列
 
要执行组件服务管理工具,按一下 开始 → 程序集 → 系统管理工具 ,然后选择 组件服务 启动主控台,如图 25-1。

 
 
图25-1 「组件服务」主控台
COM+ 应用程序服务
 
 COM+ 应用程序服务 是指利用 Microsoft 的 COM+ 规格开发出来的应用程序。COM+ 是 COM 模块的延伸。COM 就是用于分布式应用程序的开发,发展到 COM+,让安全性及队列组件更容易在应用程序上开发。
您可以在组件服务 MMC 设定您的 COM+ 应用程序组件。依下列步骤进入您的 COM+ 应用程序(如图 25-2):展开 组件服务 → 计算机 → 我的计算机 → COM+ 应用程序 。
在屏幕上您会看到所有注册过的 COM+ 应用程序。在展开您 COM+ 应用程序的数据夹后,就可以选择进入这些应用程序。

 
 
图25-2 组件服务主控台窗口内的 COM+ 应用程序
MS DTC
 
在刚刚看到的组件服务主控台窗口,COM+ 应用程序数据夹的下面的就是 MS DTC 的数据夹。我们会在下一节详细讨论 MS DTC,这一节就先不赘述。
事件检视器服务
 
这项服务工具是由 Window NT 的事件检视工具开发而来。在 Windows 2000 的事件检视器服务和在 Windows NT 的事件检视相同,允许您进入事件记录中存取数据。所有的应用程序、安全性数据、系统错误及信息数据都会存放在事件记录中,我们必须随时检查这些记录。您可以在组件服务的窗口中找到事件检视数据夹,展开此数据夹(如图 25-3),点选欲检视的的事件记录即可检视数据。

 
 
图25-3 事件检视数据夹窗口
系统服务
 
系统服务工具是由 Windows NT 服务工具发展而来。系统服务可让您检视与管理安装在系统上的所有服务工具。当您展开 服务 数据夹即可检视系统服务(如图 25-4)。

 
 
图25-4 展开 服务 数据夹检视系统服务工具。
如果要启动或是停止服务工具,点选服务工具后按鼠标右钮,在快捷菜单中选取欲执行的选项(如图 25-5)。

 
 
图25-5 快捷菜单
如果要检视或修改服务工具的属性,在上图中的快捷菜单内选取 属性 ,叫出服务工具的 属性 窗口(如图 25-6)。

 
 
图25-6 服务属性中「一般」页签的窗口
在 一般 的窗口,可以改变服务工具设定内容,也可以停止或暂停服务工具。其它的标签页允许更改该项服务登入 Windows 2000 的方式。 属性 对服务工具来说很重要。在这个设定内,可以选择当系统开启是否自动启动服务工具,或是变更 SQL Server 和 MS DTC 所使用的账户。此外,也可以指定当服务工具出现问题时该执行什么动作。在这个窗口中您还可以检视各服务间的依存性。
Microsoft 讯息队列
 
虽然服务组件 MMC 没有显示 Microsoft讯息队列(MSMQ),但因为它也利用到 MS DTC 作外部交易,因此可视为组件服务的一部份。Microsoft 讯息队列允许讯息在不同的应用程序或系统间传递交易或非交易式的讯息。应用程序利用讯息队列,在服务器间递送 耐久 讯息(durable message)。耐久讯息的意思是这个讯息不会因系统失败(如因断电而故障)而消失。假设系统突然断电,当系统回复时,MSMQ 会继续执行讯息队列。Microsoft 讯息队列利用 储存并转送(store-and-forward) 的方式来递送讯息,这种方式即使是在网络产生问题时,讯息依然会储存在队列中。讯息队列的其它功能如下:
•   可不联机送讯 :要利用讯息队列组件递送讯息,不代表必须联机;此外,讯息可以路由,这样就可以在不同通讯协议间建立连结。
 
•   可动态队列管理 :在新增或更改队列时不需重新启动讯息队列。
 
•   可排列讯息优先级 :讯息队列可依优先级将讯息排序,可以设定先传送高优先级讯息。
 
•   可以支持丛集 :讯息队列可侦测丛集,支持主动/主动(active/active)和主动/被动(active/passive)丛集。
 
•   可与 Active Directory 目录整合 :讯息队列可以利用在 Active Directory 中的目录服务。
 
•   可与 MSMQ 1 沟通 :讯息队列可与 MSMQ 1 沟通,MSMQ 1 是讯息队列前身。
 
•   可与 Windows 2000 安全性功能整合 :可利用 Windows 2000 强化后的安全功能。
 
•   讯息备份与回复 :可以将讯息备份,当系统发生问题也可以回复讯息。
 
•   使用 MMC 进行管理 :现在讯息队列管理功能和其它很多管理工具相同,都内嵌在主控台进行。
 
如您所见,Microsoft 讯息队列系统支持很多功能。不过本章会将学习重点放在讯息队列中的交易讯息组件,也就是 MS DTC。
Microsoft 分布式交易协调员
 
之前曾经提到,MS DTC 是 Windows 2000 组件服务的一部份。(MS DTC 这个观念在 SQL Server 7 就已经存在。)组件服务也包含 COM+。COM+ 是用于有非交易式通讯需求时,而 MS DTC 则用于有交易式讯息通讯需求时。
MS DTC 主要用来处理分布式交易。所谓 分布式交易 ,就是跨越两个或多个数据库的单一 SQL Server 内部的交易,这些数据库可以放在相同或分别放在不同的计算机系统内。而在同一个数据库内不同数据表间的交易,则不能称作分布式交易。在同一个系统上,数据库与数据库间的前端交易可利用一般(非分布式)处理;但是 SQL 在执行时仍会以分布式交易处理。
MS DTC 概观
 
当一笔交易包含许多不同来源的数据时,就必须协调这些提供数据的应用程序。协调的重要性在于确保交易必须是不可部份完成。换句话说,数据的修改不是全部执行,就是全部不执行。如果一笔交易部份完成,部份失败,就会造成交易逻辑没有一致性,还可能使数据流失。MS DTC 执行 两阶段交易认可(Two-Phase Commit) 确认交易逻辑。
两阶段交易认可近年来在技术上有很大的改革,这并不是新的技术,也非 SQL Server 独有。事实上,因 SQL Server 和 Oracle 两种数据库皆支持两阶段交易认可的模式及 ODBC,因此两种数据库间还可利用两阶段交易认可进行分布式交易。
两阶段交易认可的两个阶段分别为:准备阶段与认可阶段。在应用程序中以 COMMIT 指令初始化 MS DTC 执行两阶段交易认可。一台 SQL Server 上的 MS DTC,与另一个系统上的 MS DTC 协调处理一笔分布式交易。MS DTC 中处理两段交易认可的组件称作 资源管理员 。
当您执行了认可(COMMIT)指令,MS DTC 通知资源管理员开始 准备阶段 。第一阶段(也就是准备阶段),会执行所有认可所需要的动作,包括排清缓冲区和写入交易记录文件等动作。这个阶段所执行的步骤和一般的标准认可步骤类似,唯一不同的是在这里,SQL Server 不会真的认可交易,也不会对交易所用到的资源解除锁定。当所有认可交易的前置动作都完成时,资源管理员便传送准备成功的讯号给交易管理员。在所有的资源管理员都传出成功的讯号时,就进入认可阶段。
 认可阶段 在分布式系统中进行。在这个阶段,如果所有的资源管理员都传出成功讯号,应用程序端就会接受到认可成功的讯息;如果其中有一个资源管理员传出失败讯号,就会传送 复原(rollback) 指令给每位资源管理员,这时应用程序端就会收到认可失败的讯息。当系统交易时间过长,也会执行复原指令。当一个系统内的认可失败,分布式交易中所有其它相关系统也会执行复原指令。
MS DTC 使用范例
 
在这一节,我们来参考两个现实生活中用到 MS DTC 的范例,您可以看到 MS DTC 在分布式交易中的重要性,以及系统如何处理不成功的交易。
________________________________________
真实世界 银行交易
以银行间的汇款交易来说,当客户要将 A 银行账户 1 的钱汇入 B 银行账户 2 时,就银行的计算机来说就得执行两项交易:把钱从账户 1 扣除,然后把钱加入账户 2。

 
 
先来谈谈如何汇款。如果两个账户都在同一家银行,系统只要更新一个数据库的数据即可;但是如果两个账户各为不同的银行,就得启动远程交易,这笔交易对系统来说,就得处理两个交易步骤,交易可在两个系统中的其中一个系统进行,也可以在第三个系统(客户端系统)上进行。

 
 
当银行员在客户端计算机的应用程序上执行交易,应用程序开始呼叫 SQL 执行任务,SQL 会开始执行下列项目:
1. 更新系统 A,把账户 1 的金额扣除
2. 认可交易
3. 更新系统 B,把金额加入账户 2
4. 认可交易
在确定每个系统运作都完全正常的情况下,这样的运作方式是可以接受的,但却并不是一个完全安全的运作方式。例如,如果只有一个系统完成了交易,但另一个系统交易失败。以下是可能发生的情形:
•  系统 A 的交易步骤失败,系统 B 的交易无法执行,转帐失败。
 
•  系统 A 的交易步骤成功,但系统 B 的交易失败,金额就此消失。
 
这样的交易情况当然不容发生。所以下列的交易步骤才算是安全的交易程序。
1. 更新系统 A,把账户 1 的金额扣除
2. 更新系统 B,把金额加入账户 2
3. 把上述两个步骤当作一组交易程序来认可,全部认可或是全部不认可。
MS DTC 可以让您将分布式交易的认可设定为一组来认可,也就是说您可以认可一组交易步骤,如果其中一个交易步骤出了问题,就执行复原指令,这样就不会产生上述的错误。
________________________________________
________________________________________
真实世界 电子商务应用程序
电子商务的应用程序常需要同时处理大量同时发生的在线交易行为,因此需要数个系统应付庞大的交易量。一家公司如果只用一台计算机系统来应付所有的交易,并不适合,以下是一家公司可能遇到的各种状况:
•   一个系统负载过重 :每台计算机和系统都有一定的负荷量,太多的交易量容易造成单一的计算机及系统超载。
 
•   商业逻辑 :以商业逻辑而言,将不同的功能分放在不同的系统上是较合理的做法。例如,可以把使用者数据放在一个系统,产品数据放在另一个系统。
 
•   委外 :电子商务常运用委外的功能。例如,会计部分可能是委外至会计师事务所。
 
当交易需要跨越多个系统(或是一个系统里的多个数据库),就会运用分布式交易存取系统数据(或数据库)。如果不运用 MS DTC,就无法确保系统交易的不可部分完成性。
现在来看看电子商务交易如何运用分布式交易。这个范例的客户以信用卡在网络商家购物。我们来看看完成一笔交易要经过哪些步骤。
________________________________________
________________________________________
说明
电子商务的交易方式有很多种,我们这里用到的范例仅供教学参考,不代表是最佳的交易方式。
________________________________________
________________________________________
1. 客户透过网络连上网络商家的网站,还未正式进入商家的数据库。
2. 客户选择商品 A,放入电子购物车中。
3. 要完成上述动作,计算机内部就必须进入数据库执行两项交易步骤。
a. 搜寻步骤,找出客户是新客户或是旧客户,如果是旧客户就取出其 Cust_ID 的相关数据。(有些应用程序在购买步骤时,才进行搜寻步骤。)
b. 把商品 A 放入购物车数据表。
4. 当客户准备结帐,一笔交易或一组交易数据库开始执行下列运作:
a. 读取购物车数据表,找出客户购买的商品项目。
b. 更新订单数据表,确认新增的订单已加入数据表。
c. 更新客户数据库,确认账单会寄给客户。在这个范例,客户数据和订单数据是在两个不同的数据库内,所以就会运用到分布式交易。
d. 在购物车数据表中,将此商品从记录内删除。(有些应用程序在批处理时才将记录删除。)
e. 当账户数据表和订单数据表更新完成,才开始认可交易,完成分布式交易。
5. 现在,电子商家会进入货仓的数据库,备货及准备出货,完成这个程序的细节如下:
a. 查询及取出订单数据表。
b. 将查询到的货品装箱准备出货。
c. 电子商家的系统连接到信用卡处理器作付费要求。这样的交易模式也算分布式交易,因为付费要求是记录在本机端。(有些应用程序在客户结算时就先作付费要求,这样的方法并不是一般的正常程序,因为在结算时就和信用卡中心联机要求授权,会拉长交易时间。)
d. 更新订单数据表与数据库后准备出货。
6. 货物成功到达客户手中。
在这个交易中如果没有使用 MS DTC 作两阶段交易认可,就可能会产生以下的问题:
o 付费要求步骤认可成功,但订单数据表与数据库的更新过程认可失败,造成已付费但没出货。
 
o 付费要求步骤认可失败,但订单数据表与数据库更新步骤认可成功,造成出货却没收到钱。
 
o 出货步骤认可成功,但其实货还没出。
 
所以分布式交易最重要的一点就是确认交易中的每个数据库都要一并更新,不然就得一并不更新。若是交易过程没有协调,数据库之间就失去一致性,并造成很多错误。
________________________________________
MS DTC 属性
 
之前提到 MS DTC 在交易过程中的重要性。这里我们将讨论启动 MS DTC 的几种方法。
•  呼叫包含于分布式交易中的远程程序
 
•  利用 Transact-SQL(T-SQL)指令来启动分布式交易
 
•  在多个 OLE DB 数据来源更新数据
 
•  在您的应用程序中内嵌 MS DTC 指令
 
这三种方法可以让您在系统上执行分布式交易(如图 25-7)。交易初始化端的 SQL Server 执行个体将会执行所有呼叫 MS DTC 的必要操作以执行分布式交易,这个动作不需手动执行,SQL Server 会帮您打理一切细节。

 
 
图25-7 SQL Server 中初始化分布式交易
如果您用最后一种方法来启动分布式交易,客户端的应用程序接口及网络上的 SQL Server 接口会和 MS DTC 及 SQL Server 沟通。SQL Server 客户端会帮助协调分布式交易。图 25-8 为分布式交易的架构。

 
 
图25-8 在应用程序中内嵌 MS DTC 指令以初始化分布式交易
MS DTC 程序设计
 
本书不是针对程序设计者而写,所以不会在如何运用及设计分布式交易方面着墨太多;不过,本节会简单列出几种可以启动分布式交易的方法,并用简单的交易测试 MS DTC。
下列几种动作均可启动分布式交易:
•   在一笔交易中存取远程数据来源 :这样一来,这笔交易就会升级为分布式交易。在一笔交易内,任何分布式查询都会将交易升级为分布式交易。
 
•   执行 BEGIN DISTRIBUTED TRANSACTION 指令 :即可马上产生分布式交易。
 
•   使用 SQL Server 安装选项中的 REMOTE_PROC_TRAN-SACTION 选项 :执行远程呼叫程序会马上将交易升级为分布式交易。
 
•   呼叫 OLE DB 或 ODBC 函数 :OLE DB 和 SQL Server 有启动分布式交易的语法。
 
透过 T-SQL 进行分布式交易,可以测试 MS DTC。您可以利用 T-SQL 的 BEGIN DISTRIBUTED TRANSACTION 指令启动分布式交易,用 COMMIT 指令执行认可,程序如下:
BEGIN DISTRIBUTED TRANSACTION
SELECT EmployeeID FROM Northwind.dbo.Employees
SELECT emp_id FROM pubs.dbo.employee
GO
COMMIT
GO
先输入前四行的程序代码,执行后再输入最后两行程序代码。这样您可以先在分布式交易协调员(在组件服务 MMC)数据夹中的 异动清单 数据夹,检视交易。要检视这个数据夹,请展开 组件服务 → 计算机 → 我的计算机 ,最后展开 组件服务 主控台中的 Distributed Transaction Coordinator 。当交易检视完成,再输入上述 T-SQL 程序代码中的最后两行。注意,现在交易认可后,在 异动清单 数据夹就找不到这笔交易。当然,大部分的分布式交易过程是很复杂的(包括更新和插入),并不如范例这么简单。这个范例仅在不变更任何数据表的情况下提供简单的测试方式。
一般来说,分布式交易都会在一个程序中使用 ODBC 或 DB-LIB API 来呼叫启动或停止交易。分布式交易的程序设计和其它交易有一点不同的地方,就是当交易建立时必须联机,并将自动认可选项关闭,以避免 SQL 陈述式自动认可交易。当应用程序结束在 COMMIT 或 ROLLBACK 其中一个指令时,MS DTC 便开始进行两阶段交易认可。
________________________________________
相关信息
有关 SQL Server 应用程序开发,可参阅 Ron Soukup 和 Kalen Delaney 合着的《Inside Microsoft SQL Server 7.0》(Microsoft Press, 1999);如果您使用的程序语言是 Microsoft Visual Basic,可参考 William Vaughn 所著的《Hitchhiker's Guide to Visual Basic and SQL Server》(Microsoft Press, 1998)。
________________________________________
管理 MS DTC
 
MS DTC 是 Windows 2000 的安装选项。如果需要用到这个服务,只要再安装时点选即可。有两种启动 MS DTC 的方式:使用 SQL 服务管理员或利用系统服务组件中的组件服务(本章稍早有介绍)。要开启 SQL Server 服务管理员工具,点选 开始 → 程序集 → Microsoft SQL Server → 服务管理员 ,图 25-9 为服务管理员工具。

 
 
图25-9 使用 SQL Server 服务管理员开启 MS DTC
在 服务 下拉式选单选取 MS DTC 。按下 开始/继续 就可启动此服务项目,按下 停止 即可终止服务项目。您可在左下方的复选框中选择是否在开机时自动启动服务。
监控 MS DTC
 
欲监控 MS DTC,必须使用组件服务管理主控台。启动主控台(如本章之前所示范),展开 组件服务 → 计算机 → 我的计算机 → Distributed Transaction Coordinator ,如图 25-10 所示。

 
 
图25-10 组件服务中的「Distributed Transaction Coordinator」
在这个数据夹中可以看到两个选项: 异动清单 和 异动统计 。
异动清单
 
 异动清单 (如图 25-11 所示)为所有正在系统内执行分布式交易的清单,检视一笔交易的属性,并可以强制执行交易的认可或放弃。操作方式为在 异动清单 中按一下鼠标右钮,由快捷菜单中选出适合的选项。

 
 
图25-11 「异动清单」显示 MS DTC 交易
异动统计
 
 异动统计 (如图 25-12 所示)可检视分布式交易的信息,如进行中的交易笔数、最大使用量等,提供进行中分布式交易的概观,对未来容量的规划也有帮助。如您所见,分布式交易的监控、建立与执行并不困难。

 
 
图25-12 「异动统计」显示 MS DTC 交易
本章总结
 
在本章中,学到 MS DTC 的运作与分布式交易的建立,也对 Windows 2000 所提供的组件服务和技术有基本的概念,此外还学到管理部分的组件服务。以下几章将学习 SQL Server 复写。




24. 加载数据库
加载操作的效能
大量复制工具程序
BULK INSERT 陈述式
数据转换服务
Staging 资料表
SELECT...INTO 陈述式
本章总结
在学会了建立数据库和数据库数据表,就可学习加载数据了。将数据加载数据库的方法有好几种,采用何种方法取决于数据来源、对数据进行何种处理,以及资料将加载何处。本章将学习以下几种加载数据库的方法:
•   使用大量复制工具程序(Bulk Copy Program,BCP) :BCP 是由 Microsoft SQL Server 2000 提供的外部程序,便于加载数据文件至数据库,BCP 也可以从 SQL Server 中的数据表复制数据至数据文件中。
 
•   使用 BULK INSERT 指令 :BULK INSERT T-SQL 指令可从数据文件复制大量数据至 SQL Server 数据表中。由于此指令是 SQL 陈述式(在 ISQL、OSQL 或 Query Analyzer 中执行),处理过程将当成 SQL Server 的执行绪执行。该指令不能从 SQL Server 复制数据到数据文件中。
 
•   使用数据转换服务(Data Transformation Services,DTS) :DTS 是一组由 SQL Server 提供的工具组,便于复制数据到 SQL Server,或从 SQL Server 复制出数据。DTS 包括汇出和汇入数据精灵。
 
________________________________________
说明
尽管 Staging 数据表并没有提供加载数据的方法,但一般用于数据库的加载。
________________________________________
每种方法都有其特点和性质,以适合使用者不同的加载需求。
________________________________________
说明
从备份文件复原数据库也可以视为数据库加载的一种形式,这点将在 第三十二章 和 第三十三章 进行讨论。
________________________________________
BCP 或 BULK INSERT 陈述式的某些数据库参数设定是共通的,且数据库参数定义了 BCP 如何执行,因此必须在执行加载操作之前完成参数的设定。
下列的方法也很实用:
•   SELECT...INTO 陈述式 :用于将数据复制至另一个数据表。
 
•   Staging 资料表 :为暂存数据表,通常用于在数据库中转换数据,使数据加载过程更顺利,并可于加载过程中修改数据。
 
加载操作的效能
 
本段会介绍三种常用于加强加载操作效能的设定选项。其中两种选项会在执行大量复制操作时影响交易记录文件,另一种则影响锁定。使用 大量复制 的方法一次复制大量数据,可视为重建一份数据最有效率的方法。
交易记录文件选项
 
SQL Server 使用复杂的交易记录文件机制来确定数据不会因为系统故障而遗失。交易记录文件对于系统中数据的完整性是必要的,但可能会大量的增加系统负担。透过减少大量加载数据时的交易数据记录量,可降低系统的负担。
________________________________________
说明
发生系统故障后,SQL Server 会复原数据库。发生故障时还未被认可的交易都会被 复原(Roll Back) (取消操作);发生故障时已经认可的交易都会 向前复原(Roll Forward) 。复原或向前复原可以将系统复原到故障发生前的状态。备份和复原将在 第三十二章 和 第三十三章 讨论。
________________________________________
在预设状态下,所有的数据库插入操作都会被完全的记录下来,以便在系统故障时可向前复原或复原插入的数据。藉由停用大量数据复制时的完全记录(使用BCP、BULK INSERT 陈述式或 SELECT...INTO 陈述式),您可以减少记录的数据量,但也使系统只允许复原操作(认可的交易就消失了)。这个选项可使大量复制效能最佳化,但是由于用于向前复原的记录未被记录,因此当系统发生问题时,就必须重新开始数据库加载。
当满足下列状况时,大量加载操作的完全记录就会停用:
•  数据库选项 SELECT INTO/BULKCOPY 被设为 TRUE ,下列为使用sp_dboption预存程序的语法:
 
exec sp_dboption database_name, "select into/bulkcopy", TRUE
•  使用 Enterprise Manager 也可以设定该选项, 第八章 有 Enterprise Manager 的详细介绍。
 
•  加载数据的目标数据表未被设定为复写(复写在 第二十六章 、 第二十七章 及 第二十八章 有介绍)。
 
•  已经指定 TABLOCK 提示(关于提示的相关信息可参照本章 〈选择性参数〉 一节)。如果被加载的数据表已定义了索引,就不需要指定 TABLOCK 提示。
 
另外,当trunc.log on chkpt数据库选项设为 TRUE 时,会停止交易记录文件的记录。这也可改善大量复制的效能,但也代表当系统发生故障时,就无法执行向前复原或复原。
________________________________________
注意
您应该只在最初建立数据库,并且有将大量数据加载至数据库的需求时才将trunc.log on chkpt设为 TRUE,停止交易记录文件的记录会影响整个数据库,并会导致系统在发生问题时无法复原。因此在正常操作的情况下,如果「复原」这个项目对系统很重要,就不应该使用这个选项。如果已经将trunc.log on chkpt设为 TRUE,在完成加载操作后要记得将选项在设定为 FALSE。
________________________________________
trunc.log on chkpt可用sp_dboption设定,语法如下:
exec sp_dboptiondatabase_name, "trunc. log on chkpt", TRUE
________________________________________
说明
您可以在数据库 属性 窗口中的 选项 卷标页设定更多的选项,如图 24-1 所示。 限制存取 可以限制对特定角色或单一使用者存取数据库; 只读 设定不允许写入数据库。 预设为ANSI NULL 指定在预设状态下,数据库的数据行是否定义为 NULL 或 NOT NULL; 重复触发程序 让触发程序可以递归的触发; 自动更新统计资料 可让 SQL Server 在查询最佳化过程自动重建过期的统计资料; 损毁页侦测 可侦测到不完全的分页; 自动关闭 指定数据库将在其资源被释出并且所有使用者离开之后关闭; 自动压缩 指定 SQL Server 将会周期性的压缩数据库档案; 自动产生统计资料 指定查询最佳化所需的任何遗失统计数据将在最佳化过程中自动建立; 使用引号识别项 选取这个选项指定双引号只能用于识别项,例如数据行与数据表名称,而字符字符串必须括在单引号中。
________________________________________
锁定选项
 
使用table lock on bulk load选项还可改善大量复制的效能,在大量复制运作模式下,这个选项以单一数据表锁定取代多个数据列锁定。使用sp_tableoption来设定table lock on bulk load,参数的设定如下:
exec sp_tableoption "table_name", "table lock on bulk load", TRUE
加载完成后,记得要重新设定trunc.log on chkpt的参数。由于table lock on bulk load选项只有在大量复制时,才会影响数据表的锁定模式,所以当您没有执行大量复制时,不会降低执行效能。

 
 
图24-1 数据库「属性」窗口的「选项」卷标页
________________________________________
说明
要取得table lock on bulk load选项的执行效能,您必须使用 TABLOCK 设定。
________________________________________
大量复制工具程序
 
使用 BCP,可从一个数据文件中复制数据到 SQL Server,或是从 SQL Server 复制数据到数据文件中。若要将数据从其它数据库传送到 SQL Server,BCP 也很实用。本节会学习如何使用 BCP 及其选项,并学习如何将数据格式化,以便使用 BCP 将数据汇入 SQL Server 或从 SQL Server 汇出。
BCP 语法
 
 BCP 是指令行的执行程序,使用 BCP 需要特定的参数,而 BCP 提供许多选择性的参数供您使用。 BCP 指令的格式如下:
bcp {[[database_name.][owner].]{table_name|view_name} | "query"}
    {in | out | queryout | format}data_file
    [-mmax_errors] [-fformat_file] [-eerror_file]
    [-Ffirst_row] [-Llast_row] [-bbatch_size]
    [-n] [-c] [-w] [-N] [-V (60 | 65 | 70)] [-6]
    [-q] [-Ccode_page] [-tfield_term] [-rrow_term]
    [-iinput_file] [-ooutput_file] [-apacket_size]
    [-Sserver_name[/instance_name]] [-Ulogin_id] [-Ppassword]
    [-T] [-v] [-R] [-k] [-E] [-h "hint[,...n]"]
必要参数
 
必要参数指定数据的撷取和插入的位置。如之前所述,使用 BCP 可以从数据文件撷取和插入数据到一个 SQL Server 数据表或检视表中,或是从一个数据表(或检视表)撷取和插入资料到数据文件中。
在大量复制操作中所使用的数据表或检视表,可用以下两种方式指定:第一种方法为使用table/view_definition参数,最简单的定义即为数据表或检视表的名称。如之前示范过的指令,可以指定数据表或检视表所在的数据库的名称,或指定数据表或检视表的拥有者。如果不指定数据库名称,数据表或检视表所在的数据库即为使用者登入时定义的预设数据库, 第三十四章 会详细讨论使用者定义。
另一种方法为使用查询指定数据表或检视表,使用这种方法可以指定要在资料表或检视表撷取的资料。(table/view_definition参数可用来指定用于撷取或插入数据的数据表或检视表。)查询必须加上双引号,可以为加上或不加上 ORDER BY 子句的 SELECT 陈述式。指定查询定义时,必须同时指定queryout参数(将在表 24-1 讨论)。
在大量复制操作中数据文件的位置可用data_file参数指定,但所指定的路径必须是有效路径。
最后,可指定一个或多个列在表 24-1 的参数
表24-1 指定大量复制的参数
参数  描述
In 从档案夹中大量复制数据到 SQL Server 数据库的数据表或检视表中。
Out 从 SQL Server 数据表或检视表撷取及大量复制数据到档案夹中。
queryout 指定在查询大量复制数据时,才从 SQL Server 数据库中撷取查询所定义的数据,当数据经撷取查询所选出后,会大量复制到档案夹。
Format BCP 会建立新的格式文件来执行大量复制作业,所指定的格式化选项(-n、-c、-w、-6 或 -N)和资料表或检视表的分隔符可用于建立格式档。如果使用了format参数,-f 选项也必须同时指定。格式档能让您储存 BCP 定义,之后当您再度使用 BCP 时,就不需要重复定义。
选择性使用的参数
 
您可选择使用列在表 24-2 的参数以修改 BCP 执行大量复制的方式。
表24-2 指定大量复制的选择性参数
参数  描述
-a packet_size 指定在客户端和服务器端之间经由网络封包所传送的字节数目。
-b batch_size 指定每一笔批次操作所复制的数据列数,每一笔批次操作皆视为一笔交易。根据默认值,指定数据文件内的所有数据列会被当成同一笔批次操作进行复制,因此若执行大量插入数据,可能会指定此选项,以使每一笔批次操作在执行完成时,解除资料表锁定,这样便能执行其它处理程序(也就是使资源锁定的时间降低)。
-c 指定 BCP 使用 char 字符数据型别来执行大量复制作业。
-e err_file 指定 BCP 错误文件记录的路径。
-f format_file 指定 BCP 所使用过的格式文件的路径。如果 BCP 执行时使用format选项,就会建立之前所提到的格式档(format file)。如果使用了该格式档,就不需使用其它格式选项。
-h "hint[,...n]" 指定大量复制时所使用的提示,以下为可选择的提示:
•   ORDER(column[ASC | DESC]) 指定数据行中的数据排序。
 
•   ROWS_PER_BATCH = number 指定每个批次操作的数据列数目这个选项和 -b 类似,但不应和 -b 联合一起使用。-b 选项将数据列指定的批次操作视为单一交易,传送到到 SQL Server。在未指定 -b 时,整个数据文件夹会视为单一交易,传送到 SQL Server,并使用 ROWS_PER_BATCH 评估测量加载大小尺寸,使大量加载最佳化。
 
•   KILOBYTES_PER_BATCH = number 指定每笔批次操作的千字节(KB)大约数目,此选项和 -b 类似,不同之处在于此选项以千字节 KB 为单位指定批次操作大小。
 
•   TABLOCK 指定在大量复制加载期间使用数据表层级的锁定。这个提示可大为提高效能,因为减少了数据表的锁定资源竞争只在大量复制作业期间保持锁定可降低数据表的锁定争论。
 
•   CHECK_CONSTRAINTS 指定大量复制加载期间检视条件约束。根据默认值,会忽略这些条件约束。
 
-i input_file 指定响应档的名称。响应文件中包含使用互动模式执行 BCP 时,对每个字段的指令提示 BCP 问题的响应。
-k 指定空的数据行应使用保留 Null 值,而不使用是默认值。
-m max_errors 指定在结束 BCP 操作取消大量复制作业之前,允许发生错误的最多次数。如果若未包含这个选项,则默认值为 10。
-n 指定 BCP 使用 原生(native) 数据型别。
-o output_file 指定接收 BCP 输出的输出档。这个输出文件可用一般的文字文件开启,如 Microsoft 的 Notepad 或其它工具记事本等等。
-q 指定当数据表或检视表名称包含非 ANSI 字符时(例如空格键),必须使用引号识别项双引号。
-r row_term 指定数据列终止符号,默认值是新行字符(Newline Character,/n)。
-t field_term 指定字段终止符号(也称为分隔符),默认值是 tTab 字符。
-v 打印 BCP 的版本编号和版权信息。
-w 指定 BCP 使用 Unicode 字符执行大量复制作业。
-C code_page 指定数据文件中数据的字码页(Code Page)。
-E 指定在被复制的汇入的档案中包含呈现识别 Identity 数据行的值。
-F first_row 指定大量复制操作的起始第一个数据列编号。若未指定数据列编号,第一个数据列的默认值为 1。如果要跳过在数据文件的标题信息,这个选项相当适合。
-L last_row 指定大量复制操作最后结束的数据列编号,默认值为 0(0 表示结束的数据列就是数据文件的最后一个数据列),表示指定数据文件的最后一个数据列。如果只想复制特定数目的数据列,这个选项相当适合。
-N 指定 BCP 对于非字符数据使用原生数据型别;对于 Unicode 字符数据使用数据的原生数据型别,而对于字符数据则使用 Unicode 来执行大量复制作业。
-P password 指定在 -U 选项中使用者账号登入识别码的密码。
-R 针对客户端系统计算机地区设定所定义的区域格式,指定使用的货币、日期和时间数据。
-S server_name 指定要用于加载的服务器名称。
-T 指定可使用的信任联机。使用该选项后,就不需使用login_id和password变量;使用网络使用者安全凭证即可。
-U login_id 指定联机至 SQL Server 时所用的使用者账号登入识别码。
-V 60|65|70 指定使用旧版 SQL Server 的数据型别来执行大量复制作业。使用这个选项时请与字符 -c 或 -n 选项一起使用。
-6 指定 BCP 使用 SQL Server 6.0 或 SQL Server 6.5 数据型别来执行大量复制作业。
在使用 BCP 时,您可以使用单一选项或结合数个选项指定 BCP 的执行方式,取得 BCP 强大的优点。以下我们将透过范例学习使用这些选项。
使用 BCP
 
本节我们会学习使用 BCP 将数据加载或输出 SQL Server 的几个范例。这些范例并不包含所有的 BCP 使用范围,但足以示范 BCP 可使用的几个模式和方法。
您可以利用之前叙述的指令行参数,或以交互式的方式使用 BCP。要在非互动模式下使用 BCP,必须指定 -n、-c、-w 或 -N 参数。如果没有指定这些参数,BCP 会在互动模式中执行。
________________________________________
说明
以下所有范例将使用 Northwind 数据库中的Customers数据表。
________________________________________
使用 BCP 互动模式加载数据
 
在互动模式下使用 BCP 加载数据有一定的难度,因为使用时要先指定数据行长度与数据型别。当您使用指令行选项时,则不需指定这些数据,相关说明会在下一节讨论。在互动模式下使用 BCP 加载数据并不是很好的方法,以下将示范 BCP 如何在互动模式下运作,在范例中,我们会将 data2.file 数据文件中的数据复制到 Northwind 数据库的Customers数据表中,并将错误写入 err.file 档案中。您必须先建立 data2.file,该档案包含了要加载的数据。要使用系统管理员启动互动模式,请输入下列指令:
bcp Northwind.dbo.Customers in data2.file -e err.file -Usa
________________________________________
译注
如果出现无法连接 SQL Server 的错误讯息,可能是您没有指定 SQL Server 的执行个体,请使用 -S 选项指定安装在您机器上的 SQL Server 执行个体。
________________________________________
接下来会出现提示要您输入密码,请输入系统管理员(sa)的密码。
BCP 会接着要您提供欲复制数据的信息,以下为互动阶段的范例:
请输入字段 CustomerID [nchar] 的档案储存类型:char
请输入字段 CustomerID [1] 的前置长度:0
请输入字段长度 CustomerID [26]:5
请输入字段结束符号 [none]:,

请输入字段 CompanyName [nvarchar] 的档案储存类型:char
请输入字段 CompanyName [1] 的前置长度:0
请输入字段长度 CompanyName [189]:40
请输入字段结束符号 [none]:,

请输入字段 ContactName [nvarchar] 的档案储存类型:char
请输入字段 ContactName [1] 的前置长度:0
请输入字段长度 ContactName [143]:30
请输入字段结束符号 [none]:,

请输入字段 ContactTitle [nvarchar] 的档案储存类型:char
请输入字段 ContactTitle [1] 的前置长度:0
请输入字段长度 ContactTitle [143]:30
请输入字段结束符号 [none]:,

请输入字段 Address [nvarchar] 的档案储存类型:char
请输入字段 Address [1] 的前置长度:0
请输入字段长度 Address [283]:60
请输入字段结束符号 [none]:,

请输入字段 City [nvarchar] 的档案储存类型:char
请输入字段 City [1] 的前置长度:0
请输入字段长度 City [73]:15
请输入字段结束符号 [none]:,

请输入字段 Region [nvarchar] 的档案储存类型:char
请输入字段 Region [1] 的前置长度:0
请输入字段长度 Region [73]:15
请输入字段结束符号 [none]:,

请输入字段 PostalCode [nvarchar] 的档案储存类型:char
请输入字段 PostalCode [1] 的前置长度:0
请输入字段长度 PostalCode [49]:10
请输入字段结束符号 [none]:,

请输入字段 Country [nvarchar] 的档案储存类型:char
请输入字段 Country [1] 的前置长度:0
请输入字段长度 Country [73]:15
请输入字段结束符号 [none]:,

请输入字段 Phone [nvarchar] 的档案储存类型:char
请输入字段 Phone [1] 的前置长度:0
请输入字段长度 Phone [115]:24
请输入字段结束符号 [none]:,

请输入字段 Fax [nvarchar] 的档案储存类型:char
请输入字段 Fax [1] 的前置长度:0
请输入字段长度 Fax [115]:24
请输入字段结束符号 [none]:,

您要将这个格式信息存成档案?[Y/n]:Y
主檔名 [bcp.fmt]:data.fmt

开始复制…
SQLState = S1000, NativeError = 0
Error = [Microsoft][ODBC SQL Server Driver]在 BCP data-file 遇到非预
期的 EOF

已复制 5 个数据列。
网络封包大小(字节):4096
频率时间(微秒):总计  471
您在开始前必须了解上述这些值。由于没有指定复制数据列的数目,所以当 BCP 执行到档案结尾,便会出现错误讯息。
使用 BCP 与指令行选项加载数据
 
使用BCP加载数据时,使用指令行选项是较为简单的方法,本节使用的范例将使用 BCP 从一个数据文件加载数据,该数据文件使用 Tab 为字段的分隔符,并且字段型别为 char 数据型别。我们将使用 -c 选项指定在数据文件中的数据为 char 格式。使用 -c 选项也使得 BCP 在非互动模式下执行。下列的指令可将在 data.file 数据文件中 25 行的数据,复制到Customers数据表中。
bcp Northwind.dbo.Customers in data.file -e err.file -c -Usa
由于 -c 选项指定了 char 数据型别,因此不需再设定字段长度或前置长度。假设我们在 data.file 中建立 25 列数据,并且 Tab 字符分隔的数据和Customers数据表中的数据行对应,也输入了 sa 的密码,该工作阶段就会如下所示(视网络封包大小和频率可能有所不同):
开始复制…

已复制 25 个数据列。
网络封包大小(字节):4096
频率时间(微秒):总计  30
在这个范例中,复制的方向设定成In,是指数据是被加载数据库。建议您指定一个错误档案,因为错误档案可以记录在 BCP 执行期间产生的任何错误。如果您没有指定错误档案,错误会被送到屏幕上。
使用Format选项加载数据
 
在 〈使用 BCP〉 一节,我们已经建立一个名称为 data.fmt 的格式档案。您可以使用这个档案,无须再手动输入数据型别、前置长度、字段长度或字段终止符号等格式选项。使用 -f 选项就可呼叫这个档案,呼叫方法如下:
bcp Northwind.dbo.Customers in data2.file -e err.fil -f data.fmt -L
5 -Usa
假设已经输入sa的密码,并且建立了 data2.file,就会看到如以下的显示:
开始复制…

已复制 5 个数据列。
网络封包大小(字节):4096
频率时间(微秒):总计  50
除了可以使用 -f 选项,范例也包含了 -L 选项,-L 选项标示最后一个从输入文件被复制的数据列。在本例中,-L 选项指定了第 5 个数据列为最后一笔被复制的数据列,因此消除了前面看到过的 EOF 错误讯息。
使用 BCP 互动模式撷取数据
 
在互动模式中使用 BCP 从数据库中撷取数据,会比将数据复制到数据库中简单。原因是当在撷取数据时,BCP 会帮您填入字段长度的选项。现在试着用以下的指令从Customers数据表互动地复制数据。
bcp Northwind.dbo.Customers out dataout.dat -e err.file -Usa
在输入了这个指令及sa密码后就会执行以下的工作阶段:
请输入字段 CustomerID [nchar] 的档案储存类型:char
请输入字段 CustomerID [1] 的前置长度:0
请输入字段长度 CustomerID [26] :
请输入字段结束符号 [none] :,

请输入字段 CompanyName [nvarchar] 的档案储存类型:char
请输入字段 CompanyName [1] 的前置长度:0
请输入字段长度 CompanyName [189]:
请输入字段结束符号 [none]:,

请输入字段 ContactName [nvarchar] 的档案储存类型:char
请输入字段 ContactName [1] 的前置长度:0
请输入字段长度 ContactName [143]:
请输入字段结束符号 [none]:,

请输入字段 ContactTitle [nvarchar] 的档案储存类型:char
请输入字段 ContactTitle [1] 的前置长度:0
请输入字段长度 ContactTitle [143]:
请输入字段结束符号 [none]:,

请输入字段 Address [nvarchar] 的档案储存类型:char
请输入字段 Address [1] 的前置长度:0
请输入字段长度 Address [283]:
请输入字段结束符号 [none]:,

请输入字段 City [nvarchar] 的档案储存类型:char
请输入字段 City [1] 的前置长度:0
请输入字段长度 City [73]:
请输入字段结束符号 [none]:,

请输入字段 Region [nvarchar] 的档案储存类型:char
请输入字段 Region [1] 的前置长度:0
请输入字段长度 Region [73]:
请输入字段结束符号 [none]:,

请输入字段 PostalCode [nvarchar] 的档案储存类型:char
请输入字段 PostalCode [1] 的前置长度:0
请输入字段长度 PostalCode [49]:
请输入字段结束符号 [none]:,

请输入字段 Country [nvarchar] 的档案储存类型:char
请输入字段 Country [1] 的前置长度:0
请输入字段长度 Country [73]:
请输入字段结束符号 [none]:,

请输入字段 Phone [nvarchar] 的档案储存类型:char
请输入字段 Phone [1] 的前置长度:0
请输入字段长度 Phone [115]:
请输入字段结束符号 [none]:,

请输入字段 Fax [nvarchar] 的档案储存类型:char
请输入字段 Fax [1] 的前置长度:0
请输入字段长度 Fax [115]:
请输入字段结束符号 [none]:,

您要将这个格式信息存成档案?[Y/n] n
主檔名 [bcp.fmt]:

开始复制…

已复制 96 个数据列。
网络封包大小(字节):4096
频率时间(微秒):总计  20
这个互动的 BCP 工作阶段建立了一个以逗点分隔字段的档案,该档案为一文字文件,所有的数据皆为字符数据型别,可用记事本检视其内容。不过,BCP 没有在每一行的结尾加上换行字符,因此,当您使用记事本检视数据时,数据行会很长。
使用 BCP 与选择性选项撷取数据
 
要建立一个易于阅读并且加上换行字符的数据文件,您可以使用 -c 选项:
bcp Northwind.dbo.Customers out dataout.dat -e err.file -c -Usa
在输入指令与sa密码后,工作阶段执行如下:
开始复制…

已复制 96 个数据列。
网络封包大小(字节):4096
频率时间(微秒):总计  10
使用queryout选项撷取数据
 
最后我们来看看使用queryout选项撷取数据的范例,这个选项能在复制SQL Server数据库数据时指定查询,指定查询时,可选取特定的数据,并只复制被选取出来的数据。queryout的使用方法很简单,只要在双引号中包含查询即可,方法如下:
bcp "SELECT CustomerID, CompanyName FROM Northwind..Customers"
queryout dataout.dat -e err.file -c -Usa
输入sa密码后,工作阶段显示如下:
开始复制…

已复制 96 个数据列。
网络封包大小(字节):4096
频率时间(微秒):总计  1
这个查询的输出为 Tab 字符分隔的、并且每列有终止符号的数据文件。该档案的两个字段为:Customen ID和CompanyName。当在数据库撷取特定的数据行或数据列时,这个方法十分有用。
BULK INSERT 陈述式
 
T-SQL 中的 BULK INSERT 陈述式和 BCP 差不多,两者都可大量复制数据文件中的数据到 SQL Server 数据库中。然而 BCP 既可以用于复制数据也可以用于从 SQL Server 取出数据,但 BULK INSERT 只能用于数据的加载。这个限制降低了 BULK INSERT 陈述式的功能性,但是因为该陈述式可在 SQL Server 内部执行为执行绪而不是一个外部程序,所以去除了程序间的数据传送步骤,提高了数据加载的执行效能,也使得用 BULK INSERT 陈述式加载数据比 BCP 更有效率。
BULK INSERT 语法
 
和 BCP 一样,BULK INSERT 陈述式要设定几个必要参数和几个选择性使用的参数。您可以使用以下的指令,在 SQL Server 内部呼叫 BULK INSERT(使用ISQL、OSQL 或 Query Analyzer),其中包含了必要及选择性使用的参数:
BULK INSERT [[ 'database_name'.]['owner'].]
             { 'table_name' FROM 'data_file' }
    [WITH (
            [BATCHSIZE [ = batch_size ]]
            [[ , ] CHECK_CONSTRAINTS ]
            [[ , ] CODEPAGE [ = 'ACP' | 'OEM' | 'RAW' | 'code_page' ]]
            [[ , ] DATAFILETYPE   [ = {          'char' | 'native'|
                    'widechar' | 'widenative' }]]
            [[ , ] FIELDTERMINATOR [ = 'field_terminator' ]]
            [[ , ] FIRSTROW [ =first_row]]
            [[ , ] FIRETRIGGERS [ =fire_triggers]]
            [[ , ] FORMATFILE = 'format_file_path' ]
            [[ , ] KEEPIDENTITY ]
            [[ , ] KEEPNULLS ]
            [[ , ] KILOBYTES_PER_BATCH [ = kilobytes_per_batch ]]
            [[ , ] LASTROW [ = last_row ] ]
            [[ , ] MAXERRORS [ =max_errors]]
            [[ , ] ORDER({column[ ASC | DESC ]}[,...n])]
            [[ , ] ROWS_PER_BATCH [ =rows_per_batch]]
            [[ , ] ROWTERMINATOR [ = 'row_terminator' ]]
            [[ , ] TABLOCK ]
          )]
必要参数
 
数据文件的位置可用data_file参数指定,但所指定的路径必须是有效路径。
数据插入的数据库位置由数据表定义或检视表来决定。如前所述,您可以指定资料表或检视表所在的数据库名称,或指定数据表或检视表的拥有者。如果您试图用 BULK INSERT 指令将数据插入检视表,只能影响检视表中 FROM 子句所参照底层资料表的其中一个。
选择性使用的参数
 
您可以选择性的使用列在表 24-3 的参数和关键词来修改 BULK INSERT 的执行,这些选项和 BCP 的选项很相似。
表24-3 BULK INSERT 选择性使用的参数
可选择性使用的参数  描述
BATCHSIZE =size 指定每一笔批次操作中的列数,每笔批次操作皆视为一次交易。
CHECK_CONSTRAINTS 指定检查条件约束限制,根据默认值,会忽略这些限制。
CODEPAGE
[ = 'ACP' | 'OEM' | 'RAW' | 'code_page' ] 指定数据文件中的字码页,只有在数据含有char、varchar或text数据型别时,CODEPAGE 才是有用意的。
DATAFILETYPE
[ = 'char' | 'native' | 'widechar' | 'widenative' ] 指定数据文件中的数据型别,默认值的型别为char,其它的选项还包括native(原生数据型别)、widenative(Unicode 字符)和widenative(和 native 原生数据型别相同,差别在char、varchar和text是以 Unicode 储存)。
FIELDTERMINATOR [ =field_term] 指定要用于char与widechar数据型别文件中的字段终止符号端子,默认值是/t(Tab 字符)。
FIRSTROW [ =first_row] 复制的第一个数据列编号,默认值为 1,表示指定数据文件中的第一个资料列。如果要跳过在数据文件中的标题信息,就可使用此参数。
FORMATFILE [ =format_file] 指定格式文件的路径。
KEEPIDENTITY 指定保留在汇入的数据文件中呈现 Identity 识别数据行的值。
KEEPNULLS 指定空的数据行应保留 Null 值。
KILOBYTES_PER_BATCH [ =number] 指定在大量复制时,每一笔批次操作的千位组(KB)近似数据数。
LASTROW [ =last_row] 指定大量复制时,插入的最后一个数据列编号。默认值为 0,表示指定数据文件的最后一个数据列。如果只想复制特定的资料列,可以使用这个选项。
MAXERRORS [ =max_errors] 指定在大量复制插入结束之前,允许发生错误的最多次数,默认值为 10。
ORDER (column[ASC | DESC] ) 指定数据在数据文件中的排序方式。
ROWS_PER_BATCH [ =rows_per_batch]] 指定每一笔批次操作的数据列数目,每一笔批次会被视为单一交易复制。根据预值,所有在数据文件夹的资料列,会被视为单一批次操作插入,执行一次认可。当您执行大量插入时,可考虑指定这个选项,以在执行批次操作时,能解除资料表锁定,允许执行其它处理程序步骤。
ROWTERMINATOR [ =row_term] 要用于char与widechar数据型别文件的数据列终止符号端子,默认值是新增行字符(/n)。
使用 BULK INSERT
 
现在来看看使用 BULK INSERT 陈述式的两个范例,在这两个范例中,我们将会从data.file加载数据至 Northwind 数据库的Customers数据表。
________________________________________
说明
BULK INSERT 陈述式只可用于将数据加载数据库,不可用于撷取数据。由于BULK INSERT 的操作模式不如 BCP 来的多,所以这里的范例会比较少。
________________________________________
使用下列的 T-SQL 陈述式,将数据加载数据库:
BULK INSERT Northwind..Customers FROM 'C:/data.file'
WITH
     (
     DATAFILETYPE = 'char'
     )
GO
您可依需要加入更多的选项,以下的范例使用更多可选择的参数:
BULK INSERT Northwind..Customers FROM 'C:/data.file'
WITH
     (
     BATCHSIZE = 5,
     CHECK_CONSTRAINTS,
     DATAFILETYPE = 'char',
     FIELDTERMINATOR = '/t',
     FIRSTROW = 5,
     LASTROW = 20,
     TABLOCK
     )
这个陈述式只会从数据文件加载第 5 到第 20 个资料列。不管是不是默认值,字段终止符号应指定为 Tab 字符。该范例也检测大量插入过程中限制条件,并在加载过程使用数据表锁定,执行加载的交易将每 5 个数据列视为一个批次单位。
数据转换服务
 
 数据转换服务(Data Transformation Services,DTS) 是 SQL Server Enterprise Manager 的一部份,让您可以轻松将数据汇入数据库或将数据从数据库汇出。DTS 由两种精灵组成,包括 汇出精灵 和 汇入精灵 。本节将讨论如何使用这两种精灵。
汇入精灵
 
您可以透过使用汇入精灵,将不同来源的数据汇入数据库。汇入精灵和 BCP 与 BULK INSERT 陈述式不同的地方在于,汇入精灵可汇入除了数据文件外其它来源的数据,以下为使用汇入精灵的步骤:
1. 在 Enterprise Manager 中,展开一个服务器群组,并且按一下想将数据汇入的服务器。从 工具 菜单,选择 精灵 ,然后展开 数据转换服务 数据夹,选择 DTS 汇入精灵 ,按一下 确定 。将出现 数据转换服务 ─ 汇入/汇出精灵 画面,如图 24-2 所示。
 
 
图24-2 「数据转换服务─汇入/汇出精灵」画面
2. 按一下 下一步 以显示 选择数据来源 画面,如图 24-3 所示。
 
 
图24-3 「选择数据来源」画面
在这里您可以从下拉式清单中选择数据来源。我们选择了图 24-3 中的 Text File 选项,您也可从下列的数据来源选项中选择:
o dBase
 
o Microsoft Access
 
o Microsoft Data Link
 
o Microsoft Excel
 
o Microsoft Visual FoxPro
 
o Other(ODBC data source)
 
o Other OLE_DB data source
 
o Paradox
 
o Data files
 
选项的决定有部分是取决于您在安装系统时所安装的 ODBC 驱动程序,举例来说,如果安装了 Oracle ODBC 的驱动程序,清单中就会列出这个选项, 选择数据来源 画面会依照您所选择的数据来源而改变,无论选择了哪个数据来源,都需要输入档案或登入信息。
3. 按一下 下一步 以显示 选择档案格式 画面,如图 24-4 所示。这个画面只有在您选择 Text File 时才会出现,该画面允许您选择档案格式,画面中的其它选项如下:
o  使用分隔符 或 使用固定字段 允许您选择汇入档案的格式,以及特定的分隔字符或字段宽度。
 
o  档案类型 下拉式清单允许您指定汇入档案格式为 ANSI、OEM 或 Unicode。
 
o  数据列分隔符 下拉式清单允许您指定汇入档案中用什么符号来结束每一个数据列。
 
o  文字定位项 下拉式清单用来指定哪一个字符标记要用于分隔的数据文件来限定文字。
 
o  起始列号 指定开始复制的数据列编号(从档案开头为 0 号算起)。
 
o  第一列有数据行名称 指定文字文件的第一列为数据行标题而非数据。
 

 
 
图24-4 「选择档案格式」画面
4. 选择 使用分隔符 ,以 {CR}{LF} 作为资料列分隔符,将 文字定位项 设成 <无> 。按一下 下一步 以显示 指定数据行分隔符 画面,如图 24-5 所示。该画面是一个指定字段分隔符的简便方法,因为您会依所选择的选项看到选择该选项后实时的画面,以决定是否选择了适当的分隔符。您可以使用 逗号 、 Tab键 、 分号 或 其它 以选择分隔符。当您选择分隔符时,数据列会在预览窗口中显示。如果您选择的是 使用固定字段 而不是 使用分隔符 ,出现的会是 固定字段的数据行位置 画面。
 
 
图24-5 「指定数据行分隔符」画面
5. 在您选取了分隔符后,按一下 下一步 进入 选择目的地 画面,如图 24-6 所示,在这个画面之下可选择将数据汇入的数据库,您必须指定 SQL Server ODBC 目的地(数据库的 ODBC 别名)、服务器与数据库。本范例中我们会指定 Northwind 数据库,在这个画面中选择是否使用 Windows 或 SQL Server 的身份验证。如果您使用 SQL Server 身份验证,必须在空格中输入 SQL Server 使用者名称和密码,SQL Server 安全性在 第三十四章 会作详细说明。如果提供的使用者名称或密码无效,可以按一下 重新整理 按钮重试。要变更其它的属性,例如安全性选项、联机逾时等等,按一下 进阶 按钮修改,不过这些属性通常不需要更改。
6. 按一下 下一步 以显示 选取来源数据表和检视表 画面,如图 24-7 所示。在这个画面中,您可以从 数据表和检视表 中的 目的地 字段,呼叫出下拉式清单,选择数据要汇入的数据表。在这里按一下 预览 按钮,可以预览数据。 全选 和 全部不选 按钮可使您选择全部的数据表或都不选择。
 
 
图24-6 「选择目的地」画面

 
 
图24-7 「选取来源资料表和检视表」画面
7. 在相同的画面中,您可以存取转换服务,此选项可在执行数据汇入时,允许数据间的转换(更改数据行等)。要执行这个项目,按一下 转换 按钮( 转换 标题下有三个点的那个按钮),进入 数据行对应与转换 对话框,如图 24-8 所示。在 数据行对应 卷标页中,可以选择 建立目的资料表 、 删除目的表中的数据表或数据列 、 附加数据列到目的数据表 ,预设为 附加数据列到目的数据表 。如果选择 建立目的数据表 ,可以使用 编辑SQL 按钮检视及修改用于建立数据表的 SQL 陈述式。
 
 
图24-8 「数据行对应与转换」对话框内的「数据行对应」卷标页
8. 选择 转换 卷标页检视转换选项,如图 24-9 所示。在此标签页中,可选择 直接将来源数据行复制到目的数据行 或 在复制到目的地时进行信息转换 。 转换服务 的精确度转换可以在这里指定(如从 16-bit 到 32-bit;从 32-bit 到 16-bit)。NULL 值的转换也可在这里执行(如从 NOT NULL 到 NULL;从 NULL 到 NOT NULL)。
 
 
图24-9 「数据行对应与转换」对话框内的「转换」标签页
9. 按一下 确定 结束对话框,接着按一下 下一步 进入 储存、排程和复制封装 画面(如图 24-10 所示),这个画面可以决定是否现在就执行汇入,还是要安排汇入的排程。在这里也可选择 储存 DTS 封装 以便日后再次执行此汇入程序。要选择这个项目,请按一下 储存 DTS 封装 复选框(显示在下方的 储存 区域中),选取后就可储存之前选取过的所有转换服务设定。在这里我们选择 立即执行 。
10. 按一下 下一步 进入 正在完成 DTS 汇入/汇出精灵 (如图 24-11 所示),按一下 完成 执行汇入。
 
 
图24-10 「储存、排程和复制封装」画面

 
 
图24-11 「正在完成 DTS 汇入/汇出精灵」画面
11. 按一下 完成 后,会看到 正在执行封装 画面的执行(如图24-12),执行完成后会出现一个讯息,告知您汇入完成或产生错误。
 
 
图24-12 「正在执行封装」画面
使用 DTS 汇入数据很简单,但是若需要重复执行数据的汇入,建立程序代码来汇入会更有效率。您可以使用 BULK INSERT 陈述式储存在一个.sql档案内的方式,建立一个指令码档案。
汇出精灵
 
使用 汇出精灵 可将数据从数据库中汇出到外部的目的地。 汇出精灵 和 BCP 不同,可以将数据汇出到除了数据文件以外的目的地。以下为使用 汇出精灵 的步骤:
1. 在 Enterprise Manager 中,展开一个服务器群组,并且选择想将数据汇出的服务器。从 工具 菜单中,选择 精灵 ,然后展开 数据转换服务 数据夹,选择 DTS 汇出精灵 ,按一下 确定 ,会出现 数据转换服务 ─ 汇入/汇出精灵 画面,如图 24-13 所示。
2. 按一下 下一步 进入 选择数据来源 画面,如图 24-14 所示。在这里可以指定数据来源,您可以保留默认值 Microsoft OLE DB Provider For SQL Server 这个设定,或是选择 Microsoft ODBC Driver For SQL Server 。这两项选择都可以和 SQL Server 联机。其它的选项可以用于从其它种类的数据库汇出数据。选择一个数据库继续汇出步骤,在本例中我们选择 Northwind 数据库。您可以按 进阶 按钮更改进阶的选项,如联机逾时、网络位置、网络链接库和工作站 ID 等,不过这些属性通常不需要更改。
 
 
图24-13 「数据转换服务─汇入/汇出精灵」画面

 
 
图24-14 「选择数据来源」画面
3. 按一下 下一步 进入 选择目的地 画面,如图 24-15 所示。这个画面会依照选择的目的地而有所不同,但在大部分的情况下,会要求您输入登入及档案信息。在本例中我们选择 Text File 为目的地,省略输入登入及档案信息的要求,并将数据表储存成文字文件。在 文件名称 文字方块中输入目的地文件名称。
 
 
图24-15 「选择目的地」画面
4. 按一下 下一步 进入 指定数据表复制或查询 画面,如图 24-16 所示。这个画面可指定是否汇出整个数据表,还是利用查询汇出部分数据表的数据。如果您是选择了其它的 SQL Server 数据库为输出目的地,那么 在 SQL Server 数据库之间进行对象和数据的复制 这个选项就可以使用。
 
 
图24-16 「指定数据表复制或查询」画面
5. 如果选择 使用查询来指定传送的数据 后按一下 下一步 的话,会出现 键入 SQL 陈述式 画面,如图 24-17 所示。这里可键入 SQL 陈述式,只选出您想汇出的资料。查询可用于选择数据行或数据列的子集,或是选择整个数据表。
 
 
图24-17 「键入 SQL 陈述式」画面
6. 选择 下一步 进入 选择目的档案格式 画面,如图 24-18 所示。(如果您是从 键入 SQL Server 陈述式 进入本画面,在 来源 则不会显示下拉式清单。)在这个画面中可以替目的地档案指定数个格式选项,包括档案是否使用分隔符或固定字段。选定格式后按一下 下一步 。
如果您选择的是 复制来源数据库的数据表和检视表 ,按一下 下一步 同样会进入 选择目的档案格式 画面,以这种方法进入这个画面, 来源 就会出现下拉式清单。选定格式后按一下 下一步 。

 
 
图24-18 「选择目的档案格式」画面
7. 现在进入 储存、排程和复制封装 画面,如图 24-19 所示。这里可以设定是否储存 DTS 封装以便稍后执行,设定方法和之前在 汇入精灵 所介绍的类似,只是这里的选项会以反向方式执行汇出的动作。
 
 
图24-19 「储存、排程和复制封装」画面
8. 按一下 下一步 进入 正在完成 DTS 汇入/汇出精灵 画面,如图 24-20 所示。
 
 
图24-20 「正在完成 DTS 汇入/汇出精灵」画面
9. 当您按一下 完成 按钮时,汇出程序开始执行,出现 正在执行封装 画面,如图 24-21 所示,程序完成后会出现汇出成功或失败的讯息。
 汇入精灵 和 汇出精灵 的使用简化了许多设定上繁琐的步骤,但请您记得如果需要重复执行汇入或汇出的动作,花些时间写指令码会节省重复执行的时间。您可以建立使用 BULK INSERT 陈述式执行汇入或使用 SELECT 陈述式指定汇出的指令码。
________________________________________
说明
在范例中我们皆使用文字文件与数据库间的转换,事实上精灵可以执行更多数据型别的转换,特别对于数据库或其它数据来源之间转换数据,精灵尤其有用。
________________________________________

 
 
图24-21 「正在执行封装」画面
Staging 资料表
 
Staging 数据表是一个暂存数据表,您可以用来建立、处理和操作将会加载 SQL Server 的数据,并且将这些数据复制到数据库内部的适当数据表。本节会学习如何使用 Staging 数据表。
Staging 数据表基础
 
Staging 数据表是一个在数据库中的临时文件储存区,您可以将数据复制进Staging 数据表。然后您可以利用 T-SQL 执行如关联性的操作、将数据转换成想要的格式等等。这样的转换会需要用到 Staging 数据表和其它已存在的数据表。
使用 Staging 数据表处理加载的数据,可以免除某些数据加载方法对加载的限制。大部分的数据加载技术只能让数据复制到数据库,而没有加以处理。使用 DTS,可以执行一些数据转换,但是无法转换在数据库中的现有数据。使用 Staging 资料表的主要优点就是您可以基于在 Staging 数据表本身的信息或现存数据表中的信息,执行联结操作。
使用 Staging 数据表
 
本节中会用三个范例示范使用 Staging 数据表,分别是合并和加载数据表、加载及分割数据表、加载唯一值到一个数据表,这三个范例可以示范 Staging 数据表如何辅助数据的加载。
合并和加载数据表
 
想象一个在数据超市(Data Mart)中的数据表,该数据表由两个由在线交易(OLTP)系统中的数据表联合组成,该数据表有 A、B、C、D、E 五个资料行。数据行 A、B、C 在同一数据表内,而数据行 C、D、E 则在另一资料表内。这两个输入的数据表都可透过暂存方式,并且使用一个联结操作加载数据超市中,图 24-22 为操作图示。

 
 
图24-22 利用 Staging 数据表执行联结操作
加载和分割数据表
 
在第一个范例中,如果依照正常的情况,应该会将数据表加载数据超市中的数个数据表内(为了正规化的目的)。要能轻易完成这个工作,请先将数据复制到 Staging 数据表中,再使用两个查询将 Staging 数据表中的数据加载数据超市中的数据表,如图 24-23 所示。

 
 
图24-23 使用 Staging 数据表分割数据
加载唯一值到一个数据表
 
要确保加载资料的唯一性,您可以利用大量复制的方法将数据复制进 Staging 数据表中,然后使用 T-SQL 陈述式将主要数据表中没有的值,从 Staging 数据表插入主要数据表中。当加载的数据可能违反商业规则时,这个选项会很有用。使用以下的陈述式,可以将唯一值从 Staging 数据表中复制到主要数据表:
INSERT  INTO table (columnA, columnB)
SELECT  columnA, columnB
FROM    staging_table
WHERE   columnA NOT IN (SELECT  columnA
                        FROM    table)
陈述式看起来复杂,其实只不过是确认主要数据表内有没有和数据行 A 相同的数据,如果没有,则将 Staging 数据表中的两个数据行(A 和 B)加载主数据表中,以确保插入数据值的唯一性。
SELECT...INTO 陈述式
 
使用 SELECT...INTO 陈述式并不算一个正式用来加载数据的方法,比较正确的说法应该说是从已经存在的数据表或 Staging 数据表中取得数据,然后建立一个新数据表,再加载数据的方法。
________________________________________
说明
由于 SELECT...INTO 陈述式工作有一定限制,数据库选项select into/bulkcopy必须设为 TRUE。要设定该选项,请使用下面的 T-SQL 陈述式:
exec sp_dboption <database_name>, "select into/bulkcopy", TRUE
________________________________________
SELECT...INTO 陈述式的语法如下:
SELECT  <column_list>
INTO    <new_table_name>
<select_clause>
select_clause变量指的是可以和 SELECT 陈述式联合使用的陈述式或其它选项,例如 FROM 和 WHERE。SELECT...INTO 陈述式简单易用,如下面的例子。
exec sp_dboption "example", "select into/bulkcopy", TRUE
GO

SELECT  order_id,
        contact_id,
        item_id,
        item_description,
        amount INTO newsales
FROM    stage
GO

exec sp_dboption "example", "select into/bulkcopy", FALSE
GO
在这里的数据库的名称为「example」,建立一个数据表名称为newsales,取出数据的数据表是stage。
本章总结
 
在本章中,我们学到了 BCP、BULK INSERT 陈述式和 DTS 的使用方式,也介绍了 Staging 数据表和 SELECT...INTO 陈述式,这些工具和技术提供很多益处,因为加载数据至数据库正是 DBA 的主要任务之一。 第二十五章 将开始学习分布式交易协调员(MicrosoftDistributed Transaction Coordinator,MSDTC)以及 Microsoft Transaction Server(MTS)。




23. 从因特网存取 Microsoft SQL Server
因特网程序设计概念
使用 ISAPI 存取 SQL Server
使用 ASP 存取 SQL Server
使用 XML 存取 SQL Server
本章总结
在 Microsoft Windows 2000 操作系统平台上使用 Microsoft SQL Server 2000,可以让我们轻易把 SQL Server 数据库「出版(publish)」到因特网上。Windows 2000 与 Microsoft Internet Information Server(IIS)5的组合提供了包罗万象的组件与接口,这些工具与 SQL Server 2000 数据库连接与互动。本章将介绍从因特网上存取 Microsoft SQL Server 的基本观念。由于本书并非讨论程序发展的专书,因此仅提供数种不同存取方式的概观。相关程序设计的细节部分,市面上有许多不错的书籍可供参考。
本章将从因特网程序设计的概念开始,并介绍 Windows 2000 中预设的因特网程序设计界面。接着会介绍 ODBC 程序设计与 ADO 的基础观念,以及存取 SQL Server 的几种方法,包括 ISAPI 与 ASP。最后我们会讨论 XML,了解何谓 XML 以及使用方式。本章涵盖许多主题,相信应有助于了解因特网程序设计的基本工具。
因特网程序设计概念
 
本节将学到 SQL Server 与因特网应用程序连接的基本观念。这些应用程序必须包含两个不同的接口,以执行不同的任务:一个接口用于使用者,另一个则用于 SQL Server。本节将介绍应用程序与 SQL Server 之间的连接方式,包括 IIS 与 ODBC。
以 Windows 2000 与 IIS 5 作为因特网平台
 
利用 Windows 2000 与 IIS 5 作为因特网应用程序的平台,可让程序开发人员淋漓尽致地存取 SQL Server 的各种功能。程序开发人员可以利用的功能包括整合数据库存取的服务器端 script 语言、开放式数据库连接(Open Database Connectivity,ODBC)数据来源、OLE DB(一套用来存取普遍性数据的强大组件对象模型(Component Object Model,COM)接口)、以及一种被称为Internet Server API(ISAPI)的 Web 应用程序架构,最后一种架构为传统 CGI(Common Gateway Interface,共同网关接口)应用程序的强大竞争对手。
使用 ODBC 数据来源
 
就 Microsoft Windows 平台来说,ODBC 无疑是数据库接口的最佳选择。透过 ODBC,程序开发人员可以存取的资料来源类型相当广泛,从最单纯的纯文本文件到 Microsoft Excel 数据表,甚至 Microsoft Access 及 SQL Server 数据库均可存取。ODBC 提供数据库程序设计师一个通用且功能强大的抽象层级。
发展使用 SQL Server 的因特网应用程序并不需要什么特殊的手段。要透过 Web 服务器来存取 SQL Server,ODBC 数据来源已经提供了主要的一些方法。它们可以透过被称作 ActiveX Data Objects(ADO) 的一个 OLE DB COM 对象集合来完成这类工作。ADO 提供一个对象导向接口(object-oriented-interface)来存取 ODBC 数据来源,这种方法比用 ODBC C API 来得简单。利用 ADO,程序开发人员可以初始化一些简单的对象来代表数据库联机、命令(例如 SQL 陈述式或预存程序)、以及数据录集(recordsets),其类似于客户端数据指针并且具有近乎服务器端数据库数据指针的功能性。所有的这些数据库对象与界面让我们在因特网上发展使用 SQL Server 的程序变得简单,尤其是 ODBC 中更提供了一些强大的功能,例如 联机共享(connection pooling) 。
一个以 ODBC 为基础的 Web 应用程序,如何适当地利用联机共享是最要紧的问题之一。联机共享允许一个中阶的应用程序可以维护并分享与 SQL Server 数据库的联机。共享的联机在指定的时间周期内将保持开放的状态,并可分享给数个使用者。建立联机通常是一个资源密集的作业并且造成数据库服务器的负担。由于 Web 服务器与关联的因特网应用程序操纵着绝大多数的流量,透过数据库联机共享便可将建立联机以及(尤其是)重建联机的情况降至最低。如此一来,使用者联机时间可以更快,也降低了数据库服务器的资源消耗。在预设的状况下,IIS 5.0 会动态地分配数据库联机共享。
________________________________________
说明
当使用 ODBC 数据来源与 ADO 时,应以每一分页为基础使用 ADO 联机对象。相较于使用整个工作阶段对象,若在分页需要时才建立联机对象,并在不需要时立即释放它,数据库联机可更快地释放回共享状态以便其它联机使用。如此可大大地降低因特网应用程序使用者等待联机的时间。
________________________________________
选择网络链接库
 
虽然 SQL Server 可以支持命名管道及 Banyan Vines 等数种不同的网络链接库,但当您在因特网上部署一个 SQL Server 数据库时仍应使用 TCP/IP 网络链接库。在 SQL Server 网络链接库的众多选择中,TCP/IP 能提供绝佳的网络适应性,联机速度与效能。(网络链接库已在 第 11 章 解释。)
若使用 TCP/IP 作为网络链接库,SQL Server 安全性模式会被限制在只能使用标准安全性。这种模式使用 SQL Server 登入来验证。TCP/IP 并不支持整合式安全性,其使用 Windows 2000 账户来加以验证,能提供较佳的安全性以及较有效率的方法来维护 SQL Server 系统主控台里账户的集中管理。不过,使用整合式安全性相对在某些层面上也会恶化系统的效能。
首先,若使用整合式安全性,ODBC联机共享的效力就会严重受限。采取整合式安全性时,每个透过Web服务器验证进入数据库服务器的使用者必须使用唯一的登入。如此一来,联机共享所能提供的益处全然无效,因为共享的联机会被拒绝,要联机就必须使用与现存联机相同的登入与密码。
其次,以命名管道网络链接库为基础的联机多半与整合式安全性一起使用,这种联机一般说来会较为缓慢。使用命名管道还会造成联机共享的一些问题。您可以将匿名账户对应到一个有效的 SQL Server 登入,借着这个方法在命名管道连接中使用联机共享,不过多数 Web 服务器会采取挑战与响应验证模式或基本验证模式以强制单独联机至 SQL Server。结果就是否定了联机共享可提供的任何效能改善。
如果 SQL Server 与 Web 服务器是分装在不同的机器上,使用整合式安全性也会对验证模式的选择有所限制。挑战与响应验证模式将无法使用,能选择的只有基本验证模式与匿名验证模式。在因特网上让一个安全系统允许匿名验证绝不是明智的做法,而基本验证,一如刚刚所说的,则会让联机共享无法发挥。
使用 ISAPI 存取 SQL Server
 
ISAPI 是一组函式呼叫的集合,这些函式呼叫是设计来提供给因特网应用程序开发人员一个可以延伸 IIS 机能的强大工具。ISAPI 应用程序能提供卓越的效能与低阶的控制。事实上,ISAPI 应用程序在 IIS 上会比其它的 Web 应用程序来得更有效率。此外,透过 ISAPI,程序开发人员可以应用 Win32 API 的所有功能。
ISAPI 应用程序的动态链接库(DLL)有两种类别:扩充程序(extension)和筛选器(filter)。由于 DDL 是典型的编译过的程序代码,执行的速度比直译的程序代码或 script 语言要快很多。如果您的因特网应用程序在执行速度与延展性上要求很高,那么即使在程序设计与修改上会花点功夫,ISAPI 扩充程序与筛选器仍是最佳的选择。接下来的几节里我们会详细介绍 ISAPI 扩充程序与筛选器,然后解释一下 ISAPI 应用程序的设计与使用上的限制。
ISAPI 扩充程序
 
ISAPI 扩充程序的执行方式与 DLL 相同,它们会被加载到 IIS 处理空间或是与其分开的另外一个处理空间。当您在 Web 服务器上安装 ISAPI 扩充程序时可以选择加载的方式。如果应用程序不太稳定,扩充程序应该被加载到分开的处理空间,以避免一个错误的 ISAPI 扩充程序毁了整个 Web 服务器。如果 ISAPI 扩充程序还在试验阶段或是尚未完整测试,这种事是有可能发生的。
要呼叫一个 ISAPI 扩充程序,可利用 URL 中.dll的虚拟路径,例如:
http://www.mydomain.com/SampleISAPI.dll
当我们利用这种方式呼叫 ISAPI 扩充程序后,如果它尚未被加载,则此 ISAPI 扩充程序会被加载到内存中,并掌控整个要求,而 IIS 就变成服务器与客户端浏览器之间一个单纯传送数据的媒介。这种应用的一个例子是因特网站台上的自订搜寻引擎。
ISAPI 筛选器
 
ISAPI 筛选器的执行方式也与 DLL 相同,不过它们在 Web 服务器启动时便加载到 IIS 处理空间,并且保留在内存中直到服务器停止。ISAPI 筛选器可以设定来接收任何数量的筛选器事件通知,这些通知讯息在 IIS 处理每个 HTTP 要求及产生 HTTP 响应时都会出现。当一个 ISAPI 筛选器被加载后,筛选器会与 IIS 通讯,应该要通知筛选器的事件便会透过一种特殊的结构来传输。每当有类似的事件发生时,对该事件注册(registered)为应通知的筛选器便会收到一个事件通知讯息。
ISAPI 是一个功能相当强大的工具,可用来执行压缩或加密,自订的验证,Web 流量日志与分析,甚至服务器端 scripting engine。您可以建立一个 ISAPI 筛选器检查每个传送至客户端的 Web 网页设定,搜寻特殊的标签,并修改它们使其拥有一致的外观,就如同一个 ASP 网页所做的一样。
ISAPI 筛选器能够检查每个进来与出去的数据流,这种能力使它成为一个好用且很有弹性的工具。不过,如果使用太多的 ISAPI 筛选器,整个网站的效能与延展性就会彻底降低。举例来说,如果每个单一的输入与输出网页都需要筛选,就有可能因筛选器的过度活动而造成系统严重的负担。当您在决定筛选器要执行的工作时,应特别注意的是如何将其工作最小化。例如,在一个自订的加密结构里,筛选器应该只有在 IIS 需要从客户端读取数据或将数据写入到客户端时才执行加密。如此便可减少 ISAPI 筛选器应完成的工作数量。
ISAPI 的限制
 
ISAPI 技术虽然可以提供最佳的有效效能,但它也有一些缺点。由于写作 ISAPI 扩充程序与筛选器大多利用 C 或 C++,因此开发 ISAPI 扩充程序与筛选器会比开发 script 网页来得耗时,维护也会比较困难。当 ISAPI 扩充程序与筛选器需要修改时,整个应用程序都需要重新编译,而不只是替换档案。再者,即使 ISAPI 扩充程序与筛选器的执行速度一般说来会比与其功用类似的服务器端 script 程序来得快,但它们无法保证能提供最理想的延展性。最后,某些程序设计抽象过程(大部分服务器端 script 程序开发人员都认为该有的),特别是 session 对象,令人惊讶的是在 ISAPI 程序设计中竟然没有。比起服务器端 script 的程序设计,ISAPI 程序设计可说是相当低阶。
使用 ASP 存取 SQL Server
 
ASP 是一个服务器端 script 环境,程序开发人员可以利用它来建立互动的、动态的网页,进而发展出功能强大的 Web 应用程序。一个 ASP 档案是一个扩展名为 .asp 的纯文本文件,里面可包含任何文字组合、HTML 卷标、以及服务器端 script。虽然 ASP 纯粹执行于服务器端,程序开发人员仍然可以在他们的 HTML 码中包含客户端 script,并且透过用户的浏览器来执行而不是透过 Web 服务器来处理。
当 Web 服务器接收到一个对 ASP 档案的要求,Web 服务器会执行档案中包含在特殊标签内的服务器端 sript 并建立一个网页。产出的结果是纯粹的 HTML 档案,其中可包含刚刚提到的客户端 sript 组件。这个档案接着被传送到客户端的浏览器,浏览器再将这些组件执行或表现在屏幕上。不会有任何 ASP 原始码被传送到客户端。它们的分析与执行全都在服务器上完成。使用者并不会见到建立网页的 script 命令,他们看到的是这些命令建立出来的东西。
除了包含服务器端 script,ASP 档案也可以包含对 COM 组件的呼叫,以执行许多不同的任务,包括数据库存取。此外,也可执行横跨数种不同发展环境的商业逻辑对象。
ASP 在语言采用上相当中立。程序开发人员可以利用他们熟悉的 script 语言,如 Microsoft Visual Basic Scripting Edition(VBScript)、Microsoft JScript 或 Perl,来开发 ASP 档案,而发现到开发过程并不困难。ASP 网页可以使用已安装在 Web 服务器中并与 COM 兼容的 scripting engine 支持的 script 语言。 scripting engine 是一种程序,可用来处理以特定语言写成的命令。IIS 包括的 scripting engine 支持常用的 VBScript(以 Visual Basic 为基础)及 JScript(欧洲计算机制造商协会(European Computer Manufacturers Association,ECMA)262 语言规格的 Microsoft 版本)语言。从协力厂商那里可以取得像是 Perl 这类语言的 scripting engine。
ASP 具有一些超越传统 CGI 应用程序的优点。之前已经提到,对 VBScript 或 JScript 已经相当熟悉的程序开发人员将不需要学习新的程序语言,像是 C 或 Perl。ASP 提供了一些针对使用者工作阶段,要求及响应处理的对象,这使得 ASP 的功能更为强大,并且让个人化的内容开发更为容易。此外,比起利用 C 语言开发并编译的 CGI 应用程序,ASP 仅需极少的时间与程序代码便可处理与收集 HTML 窗体信息,并将其储存在数据库里。由于所有的 ASP 程序代码都是内嵌于 HTML 文件中,因此 ASP 的维护也相当容易。
使用 XML 存取 SQL Server
 
XML 是 Extensible Markup Language (延伸标记语言)的缩写,但 XML 实际上并不是一种语言。它其实是一种系统,可用来定义其它的语言,以及表达数据结构的通用语法。不同于仅仅用来指明 Web 文件呈现方式的 HTML 标记语言,XML 指定了文件的内容与结构。所谓 结构化数据(structured data) ,指的是依其内容或使用方式标记起来的数据。
XML 天生具有可延伸的特性。程序开发人员利用 XML 来定义 Web 网页内的数据,并依其需求限定细节的层级。举例来说,程序开发人员可使用 <AUTHOR> 或 <TITLE> 标签来描述书籍与出版的相关信息。如果需要额外的定义,程序开发人员可以增加 <RETAILPRICE>、<PUBLISHER>,或甚至 <ISBN> 标签。使用 XML 类似于在数据库中建立一份数据表,它必须决定应用程序需要的数据元素,就彷佛决定需要哪些数据行才能完整地描述数据表中的数据列。
由于 XML 并不描述呈现方式,因此一个 XML 文件只要写作一次便可使用不同的装置以各种方式来显示,包括 Web 浏览器、行动电话、汽车的车用显示器等等。这些装置可能有各自的显示需求:计算机屏幕也许是 800×600 像素,而一个无线的因特网装置却可能只支持 200×200 像素。由于 XML 仅定义了文件的结构与内容,这些装置只要利用各自整合的 XML 浏览器,便可将文件依其特定的显示需求呈现出来。不同于 HTML 文件,XML 文件在编写后可以用得更为长久,不会因为新的显示技术而很快被淘汰。
XML 真正有用的地方在于它可以利用 文件对象模型(Document Object Model,DOM) 来产生互动的功能。DOM 是一个接口,用来定义存取文件中数据的机制。使用 DOM,程序开发人员可以利用标准化的方式撰写动态的内容。举例来说,程序开发人员可以使用 DOM 让内容某一特定部分在一些情况下产生行为。使用这种方法可以让文件增加一些效果,例如可以让文字的某一部份-比方说,一个在 XML 中已被称为 <TITLE> 的卷标标记起来的书名-在使用者的鼠标光标滑过时会改变颜色,表示说这是一个指向某一家在线书店的超级链接。要利用目前专门的 DOM 与样式表规格来达成这类效果并不容易,不过由 W3C 制定的新的 DOM 标准将可帮助 XML 程序开发人员维护真正的平台独立。
XML 也很快地成为交换数据与文件的标准。XML 可用来在因特网上相异的数据库系统之间交换数据。举例来说,一家汽车零件供货商可利用 XML 与汽车制造商交换存货数据,即使这两家厂商可能是在两种不同的平台上使用两种完全不同的数据库系统。由于 XML 描述了数据结构的方式,因此它可以毫无问题地成为将两种既不相同也不兼容的系统之间的桥梁。
本章总结
 
在本章中,您已学习到在 Windows 2000 操作系统平台上利用 SQL Server 与 IIS 5 来开发因特网应用程序的相关基础。可用来开发应用程序的选择相当多,包括像是 ASP 这类 script 环境,或是如 ISAPI 扩充程序与筛选器这类编译程序代码,每种选择都有其各自的优点与缺点。当您在选择一个工具开发您的大型因特网应用程序,应特别注意每一种选择的交易限制以避免日后发生问题。



22. 建立及使用触发程序
什么是触发程序?
SQL Server 2000 触发程序强化功能
何时使用触发程序
建立触发程序
管理触发程序
本章总结
触发程序是一种特殊类型的预存程序。本章将学习触发程序的用途和使用方法,以及 Microsoft SQL 2000(T-SQL)触发程序引进的新功能,并将示范两种建立触发程序的方法,分别是使用 T-SQL 陈述式,和使用 SQL Server Enterprise Manager,此外,也将学习管理及修改触发程序。
什么是触发程序?
 
 触发程序(trigger) 是一种特殊的预存程序,执行特定的陈述式(UPDATE、INSERT 或 DELETE)就可以启动触发程序。触发程序与其它预存程序相同,可以是由简单,亦或是复杂的 T-SQL 陈述式组成;至于与其它预存程序不同的地方,则在于当指定的数据被修改,触发程序即自动执行,无法依名称以手动执行。触发程序执行时,称为触动(fire)。触发程序虽建立在现有的数据库数据表中,但它可以存取其它数据库的数据表和对象。触发程序不能建立在临时的数据表或临时的系统数据表上,只能建立在使用者自订数据表或自订的检视表中。执行触发程序所在的数据表或检视表,称为触发程序数据表(trigger table)。
触发程序有五种类型:UPDATE、INSERT、DELETE、INSTEAD OF 和 AFTER。有了触发程序,只要您对该表格更新、插入或删除时,就会触动对应的 UPDATE、INSERT 或 DELETE 触发程序。INSTEAD OF 和 AFTER 是 SQL 2000 新增的两项触发程序,Instead of的原义是「取代」,INSTEAD OF触发程序会取代插入、更新和删除操作而执行。AFTER 触发程序会在触发动作之后再触动,可视为控制触发程序启动时间的机制。
对数据的更新、插入及删除被视为数据修改事件。您可以设计当一项或多项修改事件产生时,即触动触发程序。例如,当执行 UPDATE 或 INSERT 陈述式时即触动触发程序。这种类型的触发程序称为 UPDATE/INSERT 触发程序。您也可以建立任何一项修改事件产生时,执行相对的 UPDATE/INSERT/DELETE 触发程序。
下面是关于触发程序的一些其它规定:
•  触发程序只在触发它的陈述式完成后执行。举例来说,如果 UPDATE 陈述式成功,UPDATE 触发程序才会被触动。
 
•  如果陈述式在数据表中执行违反条件约束或引起错误,触发程序不会触动。
 
•  触发程序视为单一交易中的一部份,因此可以由原触发程序复原交易,如果在交易过程中侦测到严重的错误(如使用者中断联机),则会自动复原整个交易。
 
•  一个陈述式只能触动一次触发程序。
 
当触发程序触动,若产生任何结果,就会如预存程序一样,将结果传回其呼叫的应用程序。一般来说,INSERT、UPDATE 或 DELETE 的陈述式(触动触发程序的陈述式)不会将结果传回;结果通常由 SELECT 查询传回。因此,为了避免触发程序传回结果给应用程序,请勿在触发过程定义中引入 SELECT 陈述式或指派变数。如果希望从触发程序中传回结果,在允许修改触发数据表的每个应用程序中都必须撰写特殊的程序,才能使应用程序收到传回的数据并进行正确的处理。
如果您必须在触发程序中指派变量,则可在触发程序的起始位置使用 SET NOCOUNT ON 陈述式以防止传回任何结果资料列。SET NOCOUNT 陈述式指定是否传回查询或受陈述式影响的数据列数目的信息(例如,影响 23 个数据列)。SET NOCOUNT 的默认值是设在 OFF,也就是说会传回受影响列的讯息。该设定并不影响 SELECT 陈述式实际结果的传回,只传回计数。
SQL Server 2000 触发程序强化功能
 
SQL Sever 2000 新增了 INSTEAD OF 及 AFTER 两项触发程序。INSTEAD OF 触发程序可以替代触发的 SQL 叙述而执行,您只能对每个陈述式(INSERT、UPDATE 与 DELETE)定义一个 INSTEAD OF 触发程序。INSTEAD OF 可以定义于一个数据表或是检视表中。若是数个检视表中都有 INSTEAD OF 触发程序,则可以在检视表中藉由定义检视表将 INSTEAD OF 触发程序串联(cascade)。若是在可更新检视表中含有 WITH CHECK 选项,则无法使用 INSTEAD OF 触发程序。若在可更新检视表中定义 INSTEAD OF 触发程序,则必须用 ALTER VIEW 命令将 WITH CHECK 选项从可更新检视表中移除。有关建立检视表的详细信息,请参阅本书 第十八章 。
AFTER 触发程序会在触发 SQL 陈述式中 所有的 动作顺利完成之后才触动,引起参考串联(referential cascade)及条件约束检查(constraint checks)动作。您可以为每个触发动作(INSERT、UPDATE 或 DELETE)指定多个 After 触发程序。如果数据表有多个 After 触发程序的话,可以使用sp_settriggerorder定义哪个 After 触发程序先触动,哪个最后触动。除了头尾两个 After 触发程序外,所有其它触发程序触动的顺序无法由您控制。
除了新增的触发程序外,SQL Server 2000 允许在数据表或检视表中定义触发程序。之前的版本仅允许在数据表中定义触发程序。检视表中的触发程序的功能定义和在数据表中的功能定义相同。
何时使用触发程序
 
触发程序和条件约束相同,可用来维持数据的完整性和商业规则,但是触发程序不能取代条件约束(条件约束在本书 第十六章 有讨论)。例如,您不需要建立触发程序来检查数据表中主索引键中的某个值是否存在,才能决定这个值是否能被插入到另一个资料表中的相对应数据行(外部索引键条件约束在这种情况下才是一个较好的选择)。您应当建立一个触发程序来启动数据库中所有相关数据表的串联变更,例如,您可能在 pubs 数据库中titles这个数据表中的title_id数据行上建立 DELETE 触发程序,当您在titles字段中删除一笔数据时,在sales、roysched和titleauthor数据表中对应数据的数据行也会被删除(在接下来的章节我们将看到如何建立该 DELETE 触发程序)。
您还可以利用触发程序执行比 CHECK 条件约束更复杂的数据检测(CHECK 条件约束在 第十六章 有详细讨论)。由于触发程序可以引用其它数据表中的数据行,因此才可能执行复杂的数据检测;反之,CHECK 条件约束只限于在其所定义的数据表上执行。
您还可以建立多重触发程序,当数据修改时即触动所有触发程序。(请记住,如果在数据表或检视表中为一个事件定义多重触发程序,每个触发程序都必须有一个自己的名称)。
或者您可以建立单一触发程序,在数据修改时即被触动。也就是每一次当被定义的事件发生,触发程序就被触动一次。因此,若是在数据表上定义 INSERT、UPDATE 和 DELETE 的触发程序,每次定义的事件产生时,触发程序就会触动。
在建立触发程序时,SQL Server 会为触发程序建立两个暂时数据表,您可以参考这两个数据表,用 T-SQL 撰写触发过程定义。这些数据表固定储存在与触发程序一起的内存中,每个触发程序只能存取自己的暂时数据表,暂时数据表即为触发程序所在数据表的一个副本。您可以使用这些数据表比较数据修改前后状态。下一节将列举这些特殊数据表(称为deleted和inserted数据表)。
建立触发程序
 
认识了触发程序以及用途,现在来了解建立触发程序的细节。首先,我们会用 T-SQL 建立触发程序,然后再学习利用 Enterprise Manager 来建立。利用 Enterprise Manager 建立触发程序,也必须了解 T-SQL 撰写程序,这和利用 Enterprise Manager 建立其它预存程序的方法是一样的。
CREATE TRIGGER 陈述式
 
要利用 T-SQL 建立触发程序,需要使用 CREATE TRIGGER 这个陈述式,以下为 CREATE TRIGGER 陈述式的基本语法:
CREATE TRIGGERtrigger_name
ON {table | name}
[WITH ENCRYPTION]
{FOR | AFTER | INSTEAD OF}
  {[DELETE] [,] [UPDATE] [,]}
    [WITH APPEND]
    [NOT FOR REPLICATION]
AS
    sql_statement[....n]
如您所视,您可以为 INSERT、UPDATE、DELETE、INSTEAD OF 或 AFTER 陈述式建立单一或一组触发程序。如果您使用 FOR 子句,则必须指定至少一个陈述式选项,该子句会指明在数据表内,哪种数据修改事件类型才可引起触发程序的触动。
当触发程序被呼叫时,会执行 AS 关键词后的 SQL 陈述式或陈述式集合,也可包含程序化结构,例如 IF 和 WHILE。以下所列出的陈述式,在触发过程定义中是不允许的:
•  ALTER DATABASE
 
•  CREATE DATABASE
 
•  DISK INIT
 
•  DISK RESIZE
 
•  LOAD DATABASE
 
•  LOAD LOG
 
•  RECONFIGURE
 
•  RESTORE DATABASE
 
•  RESTORE LOG
 
使用deleted和inserted数据表
 
之前曾提到,当建立触发程序时,您可以存取两个特定的数据表。这两个数据表虽被称为数据表,其实并不同于一般的数据库数据表,它们储存在内存中,而非在磁盘上。这两个资料表被命名为deleted和inserted。
两个数据表的结构类似(相同的数据列及同一类型的数据)于定义触发程序的数据表。deleted数据表会储存因 DELETE 及 UPDATE 陈述式而受影响的数据列副本。当数据列因触发程序被删除或更新时,被删除或更新的数据列会传送到delete数据表;在触发程序中即可使用deleted数据表。inserted数据表会储存被 INSERT 及 UPDATE 陈述式影响的数据列副本,在插入或更新交易时,新的数据列会同时被加至触发程序数据表与inserted数据表。由于执行 UPDATE 陈述式时,会被视为插入或删除交易,旧的数据列值会保留一份副本在deleted数据表中,而新的数据列值的副本则保留在触发程序数据表与inserted数据表。
当执行 INSERT 陈述式时,新增的数据列不会被传送到deleted数据表,当 INSERT 陈述式启动后去检查 deleted 数据表的内容,数据表中虽不会保有任何副本,却不会发生错误讯息。相同的,当执行 DELETE 陈述式时,删除的数据列也不会传到inserted数据表。所以,如欲检视数据修改后的状态,请参考正确的数据表。
________________________________________
说明
inserted和deleted数据表中的值只限于在触发程序中使用。一旦触发程序完成,就无法再使用这两个数据表。
________________________________________
建立第一个触发程序
 
想要看触发程序如何运作,先建立一个包含触发程序的简单数据表,并定义成当数据更新时,会打印一个陈述式。以下是建立这个数据表的 T-SQL:
USE MyDB
GO
CREATE TABLE Bicycle_Inventory
(
       make_name       char(10)     NOT NULL,
       make_id         tinyint      NOT NULL,
       model_name      char(12)     NOT NULL,
       model_id        tinyint      NOT NULL,
       in_stock        tinyint      NOT NULL,
       on_order        tinyint      NULL,
)
GO

IF EXISTS (SELECT name
           FROM    sysobjects
           WHERE   name = "Print_Update" AND
                   type = "TR")
DROP TRIGGER Print_Update
GO

CREATE TRIGGER Print_Update
ON Bicycle_Inventory
FOR UPDATE
AS
PRINT "The Bicycle_Inventory table was updated"
GO
为了测试我们的触发程序,加入数据列后更新数据表:
INSERT INTO Bicycle_Inventory VALUES ("Trek", 1, "5500", 5, 1, 0)
GO

UPDATE  Bicycle_Inventory
SET     make_id = 2
WHERE   model_name = "5500"
GO
________________________________________
译注
如果您发现执行上述 SQL 陈述式时发生错误,您可以在建立触发程序之前加上「Set Quoted_Identifier OFF」陈述式以关闭 使用引号识别项功能 。
________________________________________
因为触发程序被 UPDATE 启动,所以传回了「The Bicycle_Inventory table was updated」讯息。在这个范例中,我们将触发过程定义为当触发程序执行后即显示讯息。在某些特定的情况,可以要求触发程序传回输出结果,例如当您建立一个 UPDATE 触发程序,定义为当指定的数据列接收特定的值才触动,但是却担心数据的更新并不正确。此时若是有要求触发程序回传输出结果(在触发程序中加入 PRINT 陈述式),即可从结果中找出可能的错误;否则,一般来说您无须要求触发程序回传输出结果。
建立 DELETE 触发程序
 
现在来看一个更复杂的范例:利用 DELETE 陈述式,启动数据表的串联更新。我们将建立一个触发程序,当从titles数据表中删除数据列时,在 pubs 数据库内其它的数据表(如sales、roysched和titleauthor),与该数据相关的数据列都会一并删除。我们会利用 deleted 数据表指出哪些数据列该从相关数据表中删除。(当数据列自触发程序数据表中删除时,即在deleted数据表中会有删除数据的副本,所以您可以到deleted资料表检视所有被触发程序所删除的数据列)。要使触发程序运作,我们必须删除titleauthor、roysched和sales数据表中的外部索引键条件约束,因为这些数据表的外部索引条件约束会参考title_id列中的数据,若不删除外部索引键条件约束,触发程序会在删除title_id列时产生错误。
________________________________________
说明
如果您不介意 pubs 数据库被修改,可试着自行删除数据库中的外部索引键条件约束,然后建立触发程序。利用 Enterprise Manager 的数据库图表删除外部索引键条件约束是最简单的方法(在 第十六章 曾经说明)。请确认已删除在其它数据表中,参考title_id列数据的外部索引键条件约束。
________________________________________
本触发程序的 T-SQL 如下所示:
USE pubs
GO
IF EXISTS (SELECT name
           FROM    sysobjects
           WHERE   name = "Delete_Title" AND
                   type = "TR")
DROP TRIGGER Delete_Title
GO

CREATE TRIGGER Delete_Title
ON titles
FOR DELETE
AS
DELETE  sales
FROM    sales, deleted
WHERE   sales.title_id = deleted.title_id
PRINT   "Deleted from sales"
DELETE  roysched
FROM    roysched, deleted
WHERE   roysched.title_id = deleted.title_id
PRINT   "Deleted from roysched"
DELETE  titleauthor
FROM    titleauthor, deleted
WHERE   titleauthor.title_id = deleted.title_id
PRINT   "Deleted from titleauthor"
GO
要测试触发程序,请使用以下的 DELETE 陈述式:
DELETE  titles
WHERE   title_id = "PC1035"
GO
假设您已删除稍早提及的外部索引键,一旦执行这个 DELETE 陈述式,触发程序便会触动,您会在title数据表上看到数据修改事件影响列的讯息,接着是从触发程序中三行 PRINT 陈述式说明的讯息,并列出每个数据表中受影响的列数,输出结果如下:
(影响 1 个数据列)

Deleted from sales

(影响 5 个数据列)

Deleted from roysched

(影响 1 个数据列)

Deleted from titleauthor

(影响 1 个数据列)
deleted数据表的另一个用途,是将数据表中被删除的数据列储存到备份数据表中,以供日后的资料分析。例如,您可以利用以下的语法,从roysched数据表将被删除的数据列存入一个命名为roysched_backup的资料表中:
USE pubs
GO
CREATE TABLE roysched_backup
(
     title_id      tid  NOT NULL,
     lorange       int  NULL,
     hirange       int  NULL,
     royalty       int  NULL
)

CREATE TRIGGER tr_roysched_backup
ON roysched
FOR DELETE
AS
INSERT INTO roysched_backup SELECT * FROM deleted
GO

SELECT * FROM roysched_backup
GO
请注意,我们把备份数据表的数据行名称与数据型态,设定成和来源数据表相同。您可以自行命名数据行,但是两个数据表的数据型态应该相同,以确保数据表间的兼容性。
建立 INSERT 触发程序
 
在这个范例中,我们将建立一个 INSERT 触发程序(当 INSERT 陈述式执行时,会让此触发程序触动),当我们在sales数据表的qty数据列中插入新值,触发程序会更新titles数据表中的ytd_sales数据列。触发程序查询inserted数据表以获得刚刚插入sales数据表的qty值。我们在可在触发程序内引用 SELECT 陈述式以显示inserted数据表中所含的资料。
以下是该触发程序的 T-SQL:
USE pubs
GO
IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = "Update_ytd_sales" AND
                   type = "TR")
DROP TRIGGER Update_ytd_sales
GO

CREATE TRIGGER Update_ytd_sales
ON sales
FOR INSERT
AS
SELECT *
FROM    inserted
UPDATE  titles
SET     ytd_sales = ytd_sales + qty
FROM    inserted
WHERE   titles.title_id = inserted.title_id
GO
您可以注意到,我们在 UPDATE 陈述式中使用 FROMtable_source(FROM inserted)子句来指明qty值来源于inserted资料表。请执行下面的 INSERT 陈述式,以检视来自该触发程序的结果:
INSERT INTO sales VALUES(7066, 1, "2000-03-07", 100, "Net 30",
"BU1111")
GO
您将看到如下的结果。第一组结果显示 inserted 数据表中所选择的数据列,然后显示(影响 1 个数据列)讯息(来自 UPDATE 陈述式),如下所示:
stor_id ord_num  ord_date                 qty  payterms  title_id
------- -------- -----------------------  ---- --------  --------
7066    1        2000-03-07 00:00:00.000  100  Net 30    BU1111

(影响 1 个数据列)

(影响 1 个数据列)
建立 UPDATE 触发程序
 
接下来我们将建立一个 UPDATE 触发程序,当更新titles数据表中的price数据行时,该触发程序会检查price数据行,并验证价格上涨不超过 10%。如果超过了 10%,将以 ROLLBACK 陈述式来复原触发程序和呼叫触发程序的陈述式。如果在一个较大的交易中启动触发程序,整笔交易将被复原。在这个范例中,我们利用deleted和inserted数据表来测试价格的变化。该触发过程定义如下所示:
USE pubs
GO
IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = "Update_Price_Check" AND
                   type = "TR")
DROP TRIGGER Update_Price_Check
GO

CREATE TRIGGER Update_Price_Check
ON titles
FOR UPDATE
AS
DECLARE @orig_price money, @new_price money
SELECT  @orig_price = price from deleted
PRINT   "orig price ="
PRINT   CONVERT(varchar(6), @orig_price)
SELECT  @new_price = price from inserted
PRINT   "new price ="
PRINT   CONVERT(varchar(6), @new_price)
IF(@new_price > (@orig_price * 1.10))
BEGIN
    PRINT "Rollback occurred"
    ROLLBACK
END
ELSE
PRINT "Price is OK"
END
GO
执行以下的陈述式,来检视一本title_id为BU1111的价格,测试该触发程序:
SELECT  price
FROM    titles
WHERE   title_id = "BU1111"
GO
价格是 $11.95。接下来,执行以下陈述式,将价格增加 15%:
UPDATE  titles
SET     price = price * 1.15
WHERE   title_id = "BU1111"
GO
您会看到以下的结果:
orig price =
11.95
new price =
13.74
Rollback occurred
触发程序触动,打印出原价格及新价格,但由于价格增加超过 10%,因此将此交易复原。
现在检查价格,确认是否将修改回复。请使用下面的 T-SQL:
SELECT  price
FROM    titles
WHERE   title_id = "BU1111"
GO
因价格重设至 $11.95(而非新设至 $13.75),所以修改确实被回复。现在,我们来测试若价格修改低于 10%,价格是否会被更新。按 10% 修改价格,用以下 T-SQL 测试结果:
UPDATE  titles
SET     price = price * 1.09
WHERE   title_id = "BU1111"
GO

SELECT  price
FROM    titles
WHERE   title_id = "BU1111"
GO
价格已更新至 $13.03,由于增加少于 10%,触发程序不会被回复。
当建立一个 UPDATE 触发程序时,可以指定触发程序仅在特定的数据列更新时,才执行陈述式。例如,您可以设定只有在price数据行被更新时,才检查该数据行,确认触发程序正确触发。请使用下面的 IF UPDATE 子句:
USE pubs
GO
IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = "Update_Price_Check" AND
                   type = "TR")
DROP TRIGGER Update_Price_Check
GO

CREATE TRIGGER Update_Price_Check
ON titles
FOR UPDATE
AS
IF UPDATE (price)
BEGIN
   DECLARE @orig_price money, @new_price money
   SELECT  @orig_price = price from deleted
   PRINT   "orig price ="
   PRINT   CONVERT(varchar(6), @orig_price)
   SELECT  @new_price = price from inserted
   PRINT   "new price ="
   PRINT CONVERT(varchar(6), @new_price)
   IF(@new_price > (@orig_price * 1.10))
   BEGIN
       PRINT "Rollback occurred"
       ROLLBACK
   END
   ELSE
   PRINT "Price is OK"
END
GO
如果titles数据表的更新不包括price数据行(仅更新其它数据行),触发程序会跳过第一个 BEGIN 和 END 之间的陈述式,也跳过该触发程序。
要测试以上的触发程序是否如预期般跳过执行 BEGIN 和 END 之间的陈述式,您可以用下面的 T-SQL 陈述式,更新一个非price数据行的数据。以下的例子是将title_id为 BU1111 的这本书,更新其tyd_sales数据行的值。
UPDATE  titles
SET     ytd_sales = 123
WHERE   title_id = "BU1111"
GO
您可以看到数据行的更新不在price数据行,外部 IF 条件回传 FALSE,因此输出结果不启动触发程序的打印陈述式。利用这种方式可以避免 SQL Server 处理不必要的陈述式。
建立 INSTEAD OF 触发程序
 
INSTEAD OF 触发程序让您能控制 INSERT、UPDATE 及 DELETE 陈述式执行时所发生的事件,主要适用于联合检视表的更新。一般而言,联合检视表是不可更新的,因为 SQL Server 不知道要更新哪些基底数据表。要让检视表支持更新,您可以在检视表中定义 INSTEAD OF 触发程序,以透过检视表修改多个基底数据表。请参照以下范例:
以下范例透过使用 T-SQL 陈述式,建立一个命名为TitlesByAuthor的检视表,这个检视表会参考author、titles和titleauthor数据表的数据。(本书 第十八章 可找到更多关于检视表的数据。)
USE pubs
GO

CREATE VIEW TitlesByAuthor
AS
SELECT  authors.au_id, authors.au_lname, titles.title
FROM    authors INNER JOIN
        titleauthor ON authors.au_id = titleauthor.au_id INNER JOIN
        titles ON titleauthor.title_id = titles.title_id
GO
建立检视表后,我们利用 T-SQL 来显示所有达到检视资格的资料列:
USE pubs
GO

SELECT  *
FROM    TitlesByAuthor
GO

au_id        au_lname        title
-----------  --------------  --------------------------------------
238-95-7766  Carson          But Is It User Friendly?
724-80-9391  MacFeather      Computer Phobic AND Non-Phobic
Individuals:
756-30-7391  Karsen          Computer Phobic AND Non-Phobic
Individuals:
267-41-2394  O'Leary         Cooking with Computers:
724-80-9391  MacFeather      Cooking with Computers:
486-29-1786  Locksley        Emotional Security: A New Algorithm
648-92-1872  Blotchet-Halls  Fifty Years in Buckingham Palace
Kitchens
899-46-2035  Ringer          Is Anger the Enemy?
998-72-3567  Ringer          Is Anger the Enemy?
998-72-3567  Ringer          Life Without Fear
486-29-1786  Locksley        Net Etiquette
807-91-6654  Panteley        Onions, Leeks, and Garlic:
172-32-1176  White           Prolonged Data Deprivation: Four Case
Studi
427-17-2319  Dull            Secrets of Silicon Valley
846-92-7186  Hunter          Secrets of Silicon Valley
712-45-1867  del Castillo    Silicon Valley Gastronomic Treats
274-80-9391  Straight        Straight Talk About Computers
267-41-2394  O'Leary         Sushi, Anyone?
472-27-2349  Gringlesby      Sushi, Anyone?
672-71-3249  Yokomoto        Sushi, Anyone?
213-46-8915  Green           The Busy Executive's Database Guide
409-56-7008  Bennet          The Busy Executive's Database Guide
722-51-5454  DeFrance        The Gourmet Microwave
899-46-2035  Ringer          The Gourmet Microwave
213-46-8915  Green           You Can Combat Computer Stress!

(影响 25 个数据列)
如果您试图在au_lname数据行中删除Carson,会出现下列讯息:
服务器:讯息 4405,层级 16,状态 1,行 1
由于此修改会影响多个基底数据表,检视表或函数 'TitlesByAuthor' 无法更新。
要避免上述讯息产生,现在我们用 INSTEAD OF 触发程序来执行删除的动作,以下我们会利用一个命名为Delete_It的 INSTEAD OF 触发程序来执行删除的动作,其 T-SQL 的操作如下:
________________________________________
说明
以下的操作方式并非真正在author数据表中删除数据列,而只是重新命名这个数据列。
________________________________________
USE pubs
GO
IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = 'Delete_It' AND
                   type = 'TR')
DROP TRIGGER Delete_It
GO

CREATE TRIGGER Delete_It
ON TitlesByAuthor
INSTEAD OF DELETE
AS
PRINT   'Row from authors before deletion...'
SELECT  au_id, au_lname, city, state
FROM    authors
WHERE   au_lname = 'Carson'
PRINT   'Deleting row from authors...'
UPDATE  authors
SET     au_lname = 'DELETED'
WHERE   au_lname = 'Carson'
PRINT   'Verifying deletion...'
SELECT  au_id, au_lname, city, state
FROM    authors
WHERE   au_lname = 'Carson'
GO
利用以上的方式,即利用 T-SQL 陈述式自检视表中删除Carson,这个程序使 INSTEAD OF 触发程序触动,得到以下的输出结果:
Row from authors before deletion...
au_id        au_name         city                  state
-----------  --------------- --------------------  -----
238-95-7766  Carson          Berkeley              CA

(影响 1 个数据列)
Deleting row from authors...
(影响 1 个数据列)
Verifying deletion...
au_id        au_name         city                  state
-----------  --------------- --------------------  -----

(影响 0 个数据列)
建立 AFTER 触发程序
 
本章之前曾提到,AFTER 触发程序会在 SQL 陈述式动作触发之后才触动。您可以为每个触发动作(INSERT、UPDATE 或 DELETE)指定多个 After 触发程序。如果数据表有多个 After 触发程序的话,您可以使用sp_settriggerorder定义哪个 After 触发程序先触动,哪个最后触动。除了头尾两个 After 触发程序外,所有其它触发程序触动的顺序无法由您控制。以下是这个陈述式的语法:
sp_settriggerorder [@triggername =]'triggername',
                   [@order=] {'first' | 'last' | 'none'}
首先来看个例子。假定我们在一个数据表中定义了四个触发程序,分别命名为MyTrigger、MyOtherTrigger、AnotherTRigger和YetAnotherTrigger,当陈述式动作触发之后,让Another Trigger第一个触动,MyTrigger最后一个触动。
sp_settriggerorder @triggername = 'AnotherTrigger', @order = 'first'
go
sp_settriggerorder @triggername = 'MyTrigger', @order = 'last'
go
sp_settriggerorder @triggername = 'MyOtherTrigger', @order = 'none'
go
sp_settriggerorder @triggername = 'YetAnotherTrigger', @order = 'none'
go
上述所看到的「none」,使得介于第一个及最后一个触发程序之间启动的触发程序,以随机的顺序执行。由于随机的执行顺序是依触发程序的预设进行,因此不需特别执行sp_settriggerorder定义顺序。
建立巢状触发程序
 
 巢状触发程序(nested trigger) 是由其它触发程序所启动的触发程序,和递归触发程序不同的地方在于,巢状触发程序并不自行启动,而是当修改事件产生时,才由启动其它的触发程序所启动。SQL Server 2000 和 SQL Server 7.0 相同,第一个触发程序可以启动第二个触发程序,第二个触发程序接着启动第三个触发程序,依此类推,可以高达 32 个层级的触发程序。在 SQL Server 2000 中,巢状触发程序的预设状态设为启用,nested triggers服务器设定参数可用来控制触发程序能否巢状触发。要停止巢状触发程序,可执行以下的指令:
sp_configure "nested triggers", 0
GO
将nested triggers设成0时,则不启动巢状触发程序;将nested triggers设成1时,则可启动巢状触发程序。
接下来是巢状触发程序的范例:当一本书的标题从titles数据表中删除时,会引起巢状触发程序,以串联的方式删除相对应的数据列。在本章 〈建立 DELETE 触发程序〉 一节中,我们曾建立单一的触发程序进行数据的串联删除。我们要沿用之前的范例,但首先要删除之前范例中的触发程序避免触动,然后建立三组触发程序;第二及第三组触发程序为巢状触发程序,语法如下:
USE pubs
IF EXISTS (SELECT  name
           FROM    sysobjects
                   WHERE   name = "Delete_Title" AND
                   type = "TR")
DROP TRIGGER Delete_Title
GO

CREATE TRIGGER TR_on_titles
ON titles
FOR DELETE
AS
DELETE  sales
FROM    sales, deleted
WHERE   sales.title_id = deleted.title_id
PRINT   "Deleted from sales"
GO

CREATE TRIGGER TR_on_sales
ON sales
FOR DELETE
AS
DELETE  roysched
FROM    roysched, deleted
WHERE   roysched.title_id = deleted.title_id
PRINT   "Deleted from roysched"
GO

CREATE TRIGGER TR_on_roysched
ON roysched
FOR DELETE
AS
DELETE  titleauthor
FROM    titleauthor, deleted
WHERE   titleauthor.title_id = deleted.title_id
PRINT   "Deleted from titleauthor"
GO
欲执行触发程序,必须先删除数据表上外部索引键条件约束(如本章 〈建立 DELETE 触发程序〉 一节所示)。使用以下 DELETE 陈述式,测试是否正确执行所有触发程序。
DELETE
FROM    titles
WHERE   title_id = "PS7777"
GO
您可以看到如下的结果:
(影响 2 个数据列)

(影响 1 个数据列)

Deleted from titleauthor

(影响 2 个数据列)

Deleted from roysched

(影响 1 个数据列)

Deleted from sales

(影响 1 个数据列)
当一组巢状触发程序的任一层级失败,交易会被取消,且所有的数据修改将被复原至整组触发程序触动前的状态。
使用 Enterprise Manager 建立触发程序
 
要使用 Enterprise Manager 建立触发程序,您只需要在 触发属性 窗口中键入 T-SQL 陈述式即可,执行步骤如下:
1. 从 Enterprise Manager 中,在您想要建立触发程序的数据表名称上按右钮,开启 快捷菜单 窗口。选择 所有工作/管理触发程序 ,就会出现 触发属性 对话框,如图 22-1 所示。
 
 
图22-1 「触发属性」对话框
2. 在 文字 中输入触发程序的 T-SQL 语法(图 22-2)。
3. 按一下 检查语法 按钮以核对语法。语法如正确会显示 语法检查成功 。
窗口(图 22-3)。按一下 确定 以建立触发程序。现在触发程序 Print_Update 出现在 名称 下拉式清单中,如图 22-4 所示。
4.  触发属性 窗口保持开启的状态,使您可以在资料表上建立其它的触发程序。如果您没有其它的触发程序要建立,按一下 关闭 。
 
 
图22-2 输入触发程序语法后的「触发属性」对话框

 
 
图22-3 语法检查成功窗口

 
 
图22-4 下拉式清单中新建立触发程序的名称
管理触发程序
 
在本节中,我们先学习使用 T-SQL 管理触发程序,然后再学习如何使用 Enterprise Manager 管理。
使用 T-SQL 管理触发程序
 
T-SQL 指令可用于管理触发程序。您可以检视触发程序程序语法、存在于特定数据表上的触发程序、更改触发程序语法、删除触发程序、启动或停止触发程序。本节中将会说明这些选项。
检视触发程序语法
 
sp_helptext和sp_helptrigger两种系统预存程序能提供检视触发程序的相关信息。若要显示用来建立程序的文字,可在预存程序名称之前执行sp_helptext。举例来说,若要显示之前建立Print_Update这个触发程序中的文字定义,可使用下面的指令:
USE MyDB
GO
sp_helptext Print_Update
GO
输出结果如下:
Text
-----------------------------
CREATE TRIGGER Print_Update
ON Bicycle_Inventory
FOR UPDATE
AS
PRINT "The Bicycle Inventory table was updated."
检视数据表中现存的触发程序
 
要检视存在特定数据表中的触发程序(或检视触发程序是否存在),可在数据表名称之前执行sp_helptrigger预存程序。要检视范例数据表MyTable的触发程序,请使用下面的指令:
USE MyDB
GO
sp_helptrigger MyTable
GO
输出结果如下:
trigger_name trigger_owner isupdate  isdelete  isinsert isafter isinsteadof
------------ ------------  --------- --------- -------- -------- ---------
Print_Update dbo           1         0         0        1        0

(影响 1 个数据列)
输出结果显示触发程序名称、触发程序拥有者,以及启动触发程序的数据修改事件类型。如果触发程序因该类型的数据修改事件启动,输出结果数据行isupdate、isdelete、isinsert、inafter和isinsteadof的值则为1,如果没有启动则为0。如果触发程序因多种类型的数据修改事件触动,就会有多个资料行含有值1。
使用 ALTER TRIGGER
 
要改变先前建立的触发过程定义,可以删除后重建触发程序,也可以使用 ALTER TRIGGER 陈述式,这个陈述式使用和 CREATE TRIGGER 陈述式相同的语法。如果要改变触发程序,必须重新定义整个触发程序。举例来说,要改变Print_Update触发程序对Bicyle_Inventory的数据修改方式(当 INSERT 或 UPDATE 陈述式执行时即会触动),可执行以下语法:
USE MyDB
GO
ALTER TRIGGER Print_Update
ON MyTable
FOR UPDATE, INSERT
AS
PRINT "Bicycle_Inventory was updated or a row was inserted"
GO
现在先前所定义的触发程序已被更新过的版本所代替。现在如果在Bicycle_Inventory上执行 UPDATE 或 INSERT,触发程序即会触动,以下为执行的语法:
INSERT INTO Bicycle_Inventory VALUES ("Trek",1,"Lance S.E.",1,0,1)
GO
UPDATE  Bicycle_Inventory
SET     in_stock = 1
WHERE   model_name = "Lance S.E."
GO
使用 DROP TRIGGER
 
要从数据表中完全删除触发程序,可利用 DROP TRIGGER 陈述式。删除的语法如下:
DROP TRIGGERtrigger_name
要删除Pring_Update触发程序,可使用下面的陈述式:
USE Bicycle_Inventory
GO
DROP TRIGGER Print_Update
GO
如果现在检视存在于MyTable数据表上的所有触发程序,会发现该触发程序已不存在,可以使用以下语法检视:
USE MyDB
GO
sp_helptrigger MyTable
GO
________________________________________
说明
如果您删除一个数据表,该数据表上的所有触发程序都会被自动删除。
________________________________________
启动和停止触发程序
 
利用 ALTER TABLE 陈述式,不用删除触发程序即可变更触发程序的定义,由于每个触发程序都定义在一个特定数据表上,所以使用 ALTER TABLE 陈述式来代替 ALTER TRIGGER 陈述式。使用以下语法,重建本章中第一个范例的触发程序:
USE MyDB
GO
IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = "Print_Update" AND
                   type = "TR")
DROP TRIGGER Print_Update
GO

CREATE TRIGGER Print_Update
ON Bicycle_Inventory
FOR UPDATE
AS
PRINT "The Bicycle_Inventory table was updated"
GO
触发程序在一开始会自动启用。关闭触发程序可使它不被启用(直到重新启用为止),但是其定义仍然存在于该数据表上。可使用下面的 DISABLE TRIGGER 选项关闭触发程序:
ALTER TABLE Bicycle_Inventory
DISABLE TRIGGER Print_Update
GO
现在当Bicycle_Inventory上发生更新时,Print_Update触发程序不会触动。欲重新启动触发程序,可利用 ENABLE TRIGGER,语法如下:
ALTER TABLE Bicycle_Inventory
ENABLE TRIGGER Print_Update
GO
ENABLE TRIGGER 和 DISABLE TRIGGER 子句可使触发过程定义保持不变,视需要而开启或关闭该触发程序即可。
使用 Enterprise Manager 管理触发程序
 
您也可以使用 Enterprise Manager 管理触发程序,尽管可使用图形化使用接口管理触发程序,仍需撰写 T-SQL 程序语法。
删除触发程序
 
要使用 Enterprise Manager 删除触发程序,按照下面的步骤:
1. 在数据表名称上按右钮叫出快捷菜单,选择 所有工作/管理触发程序 。
2. 从 名称 下拉式清单中选择触发程序名称,然后按一下 删除 。
3. 当询问您是否确定想要删除触发程序时,按一下 确定 (如图 22-5)。
 
 
图22-5 确定是否删除触发程序的对话框
修改触发程序
 
按照以下步骤,即可使用 Enterprise Manger 修改触发程序
1. 在数据表名称上按右钮叫出快捷菜单,选择 所有工作/管理触发程序 。
2. 从 名称 下拉式清单中选择触发程序名称。
3. 在 文字 方块中编辑 T-SQL 语法,使用 Ctrl+Tab 键来排缩触发程序的文字。您可以使用 CREATE TRIGGER 或 ALTER TRIGGER 陈述式,不论使用其中的哪一种,SQL Server 会删除现存的触发程序并且使用其中一种陈述式重建触发程序,依这样的操作,您不会得到在使用交互式 OSQL 或ISQL 时,所会出现的错误讯息。完成编辑后,按一下 确定 ,SQL Server 将会自动修改触发过程定义。
本章总结
 
在本章中,我们学习了何谓触发程序,并认识了五种类型的触发程序,分别是 INSERT、UPDATE、DELETE、ALTER 和 INSTEAD OF,还学到了使用 T-SQL 和 Enterprise Manager 建立及管理触发程序。下一章,我们将利用 ADO 及 XML,透过因特网存取 SQL Server 2000。




21. 建立及管理预存程序
何谓预存程序?
建立预存程序
使用 T-SQL 管理预存程序
本章总结
本章将学习 Microsoft SQL Server 预存程序以及使用方法。首先会介绍预存程序的类型,接着学习建立及管理使用者自订的预存程序与定义参数及变量。建立预存程序的方法有四种,本章会叙述如何使用 Transact-SQL(T-SQL)、SQL Server Enterprise Manager 和建立预存程序精灵,第四种方法为使用 SQL Distributed Management Objects(SQL-DMO),因为该方法与应用程序设计相关,故在此将不作讨论。在操作的过程中可以发现,三种建立预存程序的方法都要利用到 T-SQL 程序代码,本章的 〈使用 CREATE PROCEDURE 陈述式〉 一节中会介绍到 T-SQL 程序代码,请特别留意 T-SQL 程序代码的用法。
何谓预存程序?
 
 预存程序(stored procedure) 是 T-SQL 陈述式的集合,SQL Server 会将该集合中的陈述式编译成一个执行计划单位。当预存程序第一次执行时,经过编译的执行计划即储存在内存的程序快取区中,并且可以重复使用,这样 SQL Server 就不必在每一次执行相同的任务时重复分析语法是否正确。预存程序和其它程序语言的程序相似,可以接受传入的参数、将参数的值传回,或是传回成功或失败状态的讯息。当程序被呼叫时,所有在程序中的陈述式都会被执行。预存程序会执行某项任务所需用到的 T-SQL 陈述式及相关逻辑。由于预存程序可视为一个执行单位,因此可由不同的使用者,重复地执行在同样的任务上,甚至可跨多应用程序作业。预存程序也为作业提供了单一控制点,确保执行商业规则的正确性与一致性。
您的应用程序端可以透过两种方法与 SQL Server 通讯:您可以撰写应用程序以从客户端传送 T-SQL 陈述式到 SQL Server 中,或者自行建立预存程序以在服务器上储存及执行。如果您从客户端应用程序传送 T-SQL 陈述式到服务器,陈述式会透过网络传输,并在每次执行时进行编译。如果使用预存程序,您可以藉由一个陈述式,从应用程序中呼叫预存程序并执行该预存程序。如之前所提到的,SQL Server 会对第一次执行的预存程序进行编译,将此执行计划储存在内存中。当下一次再呼叫相同的执行计划,就不需再重复编译。当一项工作执行时需要多项 T-SQL 陈述式,或某些陈述式经常要执行,使用预存程序就不需要每次执行一项陈述式,就得透过网络从客户端传回结果,从而减少网络的流量和系统的负担。
预存程序也可透过其它方法提高执行效能。举例来说,透过预存程序可减少客户端和服务器端间传送的数据量,客户端所需处理的资料量相对减少,因此利用预存程序在服务器上执行,就是一种提高执行效能的方法。若是在预存程序内部测试条件判断式,可以在预存程序中应用条件陈述式(如在 第二十章 中讨论的 IF 和 WHILE 结构)。这种测试逻辑会透过预存程序在服务器上执行,无须将逻辑写入应用程序里,并且服务器不必立即传回结果到客户端以执行测试条件。您还可以从指令码、批处理,或利用 T-SQL 陈述式的交互式命命列来呼叫预存程序(本章稍后会介绍)。
预存程序还为使用者提供了简单的数据库存取方式。使用者不必知道数据表的结构详细信息就可以存取数据库,换句话说,他们只要执行所需的任务,而不需要直接进入数据表。预存程序即是以此方式确保商业规则。
预存程序可以接收输入参数,使用区域变量,以及传回数据。预存程序透过输出参数、回传SELECT陈述式执行的结果、或全域数据指针(global cursor)传回数据。除了使用全域数据指针,其它的技巧在本章稍后都会有范例。
________________________________________
相关信息
关于全域数据指针的数据,您可在《在线丛书》的 搜寻 标签页中,输入「指针」这个关键词,在 Transact-SQL程序语法参考说明 这个位置,选择 DECLARE CURSOR ,即可找到联机全域数据指针的相关数据。
________________________________________
预存程序共分三种类型: 系统预存程序 、 延伸预存程序 、 简易使用者自订预存程序 。 系统预存程序(system sotred procedure) 由SQL Server所内建,并且有前缀sp_,用于管理 SQL Server 和显示数据库和使用者信息,在 第十三章 中作过介绍; 延伸预存程序(extended sotred procedure) 属于动态链接库(DLLs),SQL Server 可以动态加载与执行,通常是使用 C 或 C++ 语言写成,包含前缀xp_; 简易使用者自订预存程序 由使用者自行建立自订执行使用者指定的任务。
________________________________________
说明
当建立简易使用者自订预存程序时,不应该使用sp_当前缀,因为当SQL Server 遇到有前缀为sp_的预存程序时,会先在 master 数据库中寻找预存程序。举例来说,如果在 MyDB 数据库中,将自订的简易使用者预存程序命名为sp_myproc,SQL Server 会先在 master 数据库中寻找该预存程序(当然是找不到),然后才会去使用者数据库寻找。因此将程序简单的命名为myproc会更有效率。
________________________________________
我们会先简单的介绍延伸预存程序,本章的重点则会放在简易使用者自订预存程序。延伸预存程序因为可利用诸如 C、C++ 等程序语言建立自己的外部例程,扩充了 SQL Server 环境的使用性及延展性,执行时和其它两种类型的预存程序相同,即可以传送参数给延伸预存程序,也可以传回结果集和状态。
如前所述,延伸预存程序属于动态链接库(DLLs),SQL Server 可以动态加载与执行,并直接在 SQL Sever 地址空间中执行。您可以使用 SQL Sever Open Data Services API 撰写程序。
延伸预存程序可以在 SQL Sever 以外环境撰写,当一个延伸预存程序撰写完成,可利用 T-SQL 命令或利用 Enterprise Manager 注册该延伸预存程序。
________________________________________
相关信息
在 SQL Sever《在线丛书》可找到更多延伸预存程序的使用范例。
________________________________________
建立预存程序
 
本节会介绍建立预存程序的三种方法:T-SQL 的 CREATE PROCEDURE 陈述式、Enterprise Manager 和建立预存程序精灵。
使用 CREATE PROCEDURE 陈述式
 
CREATE PROCEDURE 陈述式的基本语法如下:
CREATE PROCEDURE [procedure_name]
                 [{@parameter_name data_type}] [= default][OUTPUT]
                 [,...,n]
AS t-sql_statement(s)
首先我们建立一个简单的预存程序,此预存程序会在Orders数据表中的每一数据列,选择(并传回)三个数据行中的数据,当ShippedDate数据行中的日期晚于RequiredDate的日期,就会传回数据。请注意,预存程序只能建立在使用中的数据库上,所以必须先利用 USE 陈述式来指定数据库。在建立预存程序前,要先确定是否有重复的名称存在,我们必须用未存在的名称命名预存程序,或是先删除已经存在的名称后再重新命名。用于建立该程序的 T-SQL 程序代码如下:
USE Northwind
GO

IF EXISTS (SELECT name
           FROM   sysobjects
           WHERE  name = "LateShipments" AND
                  type = "P")
DROP PROCEDURE LateShipments
GO

CREATE PROCEDURE LateShipments
AS
SELECT  RequiredDate,
        ShippedDate,
        Shippers.CompanyName
FROM    Orders, Shippers
WHERE   ShippedDate     > RequiredDate AND
        Orders.ShipVia  = Shippers.ShipperID
GO
执行上述的 T-SQL 程序代码就会建立预存程序,要执行该预存程序,只要呼叫其名称:
LateShipments
GO
LateShipments会传回 37 列资料。
如果呼叫该预存程序的陈述式是一个批次中的陈述式,并且不是该批次操作的第一个陈述式,就必须使用 EXECUTE(可缩写为 EXEC)关键词呼叫,使用范例如下:
SELECT getdate ( )
EXECUTE LateShipments
GO
如果呼叫程序的陈述式为该批次操作的第一个陈述式,或为该批次操作的唯一陈述式,您也可以不使用 EXECUTE 关键词。
使用参数
 
接下来让我们在这个预存程序中,新增一个输入参数,以便在呼叫预存程序时,同时也传递参数给预存程序。要想在预存程序中指定输入参数,请以 @ 前缀为参数名称的前置字,例如@parameter_name,一个预存程序可指定高达 1024 个参数。在范例中,将建立@ShipperName的参数。当执行预存程序时,输入船公司名称,该查询就只会传回该船公司的数据列,其 T-SQL 陈述式如下:
USE Northwind
GO

IF EXISTS (SELECT name
           FROM   sysobjects
           WHERE  name = "LateShipments" AND
                  type = "P")
DROP PROCEDURE LateShipments
GO

CREATE PROCEDURE LateShipments @shipperName char(40)
AS
SELECT  RequiredDate,
        ShippedDate,
        Shippers.CompanyName
FROM    Orders, Shippers
WHERE   ShippedDate             > RequiredDate AND
        Orders.ShipVia          = Shippers.ShipperID AND
        Shippers.CompanyName    = @shipperName
GO
执行此预存程序时,必须先提供输入参数,否则会显示如下的错误讯息:
服务器:讯息 201,层级 16,状态 4,程序 LateShipments,行 0
程序 'LateShipments' 预期使用未提供的参数 '@shipperName'
想为 Speedy Express 这家船公司传回符合要求的数据列,请执行以下陈述式:
USE Northwind
GO
EXECUTE LateShipments "Speedy Express"
GO
该预存程序将传回 12 个数据列。
您也可以为参数设定默认值,它将适用于当呼叫预存程序时没有参数的情况。举例来说,我们将预存程序的参数默认值设为 United Package,其 T-SQL 预存程序程序代码变更如下(只变更 CREATE PROCEDURE 行):
USE Northwind
GO
IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = "LateShipments" AND
                   type = "P")
DROP PROCEDURE LateShipments
GO

CREATE PROCEDURE LateShipments @shipperName char(40) = "United
Package"
AS
SELECT  RequiredDate,
        ShippedDate,
        Shippers.CompanyName
FROM    Orders, Shippers
WHERE   ShippedDate          > RequiredDate AND
        Orders.ShipVia       = Shippers.ShipperID AND
        Shippers.CompanyName = @shipperName
GO
如果在执行LateShipments时没有提供参数,预存程序将使用United Package为@ShipperName的默认值(并传回 16 个数据列)。即使预设参数已经确定,仍然可以提供输入参数,此参数会覆写默认值。
如果您想在预存程序中传回值给呼叫程序,请在参数名称后使用 OUTPUT 关键词。要将值储存在变量中以供呼叫预存程序的应用程序使用,也可以在呼叫该预存程序时,使用 OUTPUT 关键词。让我们实际操作一个范例,首先建立新的预存程序以为某个产品选择单价,@prod_id为 ProductID 的输入参数,@unit_price输出参数将传回单价,名称为@price的区域变量将在呼叫程序中被宣告,并用于储存传回值。下面是用于建立GetUnitPrice预存程序的程序代码:
USE Northwind
GO

IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = "GetUnitPrice" AND
                   type = "P")
DROP PROCEDURE GetUnitPrice
GO

CREATE PROCEDURE GetUnitPrice @prod_id int, @unit_price money OUT-
PUT
AS
SELECT  @unit_price = UnitPrice
FROM    Products
WHERE   ProductID = @prod_id
GO
您必须在呼叫程序中宣告变量,才可在预存过程调用中使用该变量。举例来说,在下面的程序代码中我们先宣告@price变量并将其数据型别设为money(它必须符合OUTPUT参数数据型别),然后执行此预存程序:
DECLARE @price money
EXECUTE GetUnitPrice 77, @unit_price = @price OUTPUT
PRINT CONVERT(varchar(6), @price)
GO
PRINT 陈述式为@price传回值13.00。请注意我们用 CONVERT 陈述式将@price由原来的money数据型别,转换为varchar数据型别,才可以将该值当成字符串、字符数据型别,或以不直接的方式转换成字符来打印(这些是 PRINT 陈述式的打印要求)。请注意在预存程序和呼叫程序中为 OUTPUT 使用不同名称的变量,以使您能够更方便的找到范例中变量的位置,并强调名称可以不同。
您也可以在执行预存程序时,使用变量指定输入值,让预存程序可以接收来自呼叫程序的数值,然后修改该值或利用该值以执行某种作业,再将新的值传回呼叫程序。操作方法为在执行预存程序前,先为呼叫程序中的某变量分配一个值(或执行查询以在变量中插入值),再将该变量传送到预存程序中。现在就来看看如何在预存程序中使用区域变量。
在预存程序中使用区域变量
 
DECLARE 关键词用于建立区域变量,在建立区域变量时,就要指定区域变量名称及数据型别,而名称必须以 @ 前缀为前置字。一但变量宣告,其值会先被设为 NULL。
区域变量可在批次操作、指令码(或呼叫程序)或预存程序中宣告。预存程序中的变量通常用来储存条件陈述式所测试传回的数据值,或是储存预存程序 RETURN 陈述式所传回的数据值。变数也常被用来当作计数器。变量范围从变量的宣告处开始,宣告该变量的预存程序结束后,该变量就不再有效。
现在就来看一个包含区域变量的预存程序。该预存程序使用 WHILE 循环结构插入五个数据列到数据表中。首先建立一个范例数据表,命名为mytable,然后建立一个预存程序,命名为InsertRows。在程序中将使用@loop_counter和@start_val这两个区域变量,我们会一起宣告这两个变量,并且以逗号将两变量区隔。以下为使用 T-SQL 程序代码建立数据表和预存程序的方法:
USE MyDB
GO

CREATE TABLE mytable
(
     column1 int,
     column2 char(10)
)
GO

CREATE PROCEDURE InsertRows @start_value int
AS
DECLARE @loop_counter int, @start_val int
SET     @start_val = @start_value - 1
SET     @loop_counter = 0
WHILE (@loop_counter < 5)
   BEGIN
      INSERT INTO mytable VALUES (@start_val + 1, "new row")
      PRINT (@start_val)
      SET @start_val = @start_val + 1
      SET @loop_counter = @loop_counter + 1
   END
GO
现在执行起始值为 1 的预存程序,如下所示:
EXECUTE InsertRows 1
GO
执行后会打印五个@start_val值:0、1、2、3和4。使用下面的陈述式从mytable中选择所有的数据列:
SELECT *
FROM mytable
GO
在执行 SELECT 陈述式后,会出现如下的输出:
column1  column2
-------- ----------
1        new row
2        new row
3        new row
4        new row
5        new row
当结束预存程序后,@loop_counter和@start_val就无法再被存取。先使用下面的 T-SQL 陈述式尝试打印:
PRINT (@loop_counter)
PRINT (@start_val)
GO
就会得到这样的错误讯息:
服务器:讯息 137,层级 15,状态 2,行 1
必须宣告变量 '@loop_counter'
服务器:讯息 137,层级 15,状态 1,行 2
必须宣告变量 '@start_val'
执行批次陈述式操作时,此变量范围的规则也适用。一旦宣告关键词 GO(表示批次陈述式结束),批次陈述式所宣告的区域变量将不能再被使用,区域变量的范围仅限该批次陈述式使用。以下的预存过程调用能让您了解这个规则:
USE Northwind
GO

DECLARE @price money
EXECUTE GetUnitPrice 77, @unit_price = @price OUTPUT
PRINT CONVERT(varchar(6), @price)
GO

PRINT CONVERT(varchar(6), @price)
GO
第一个 PRINT 陈述式打印了批次操作中的区域变量@price;第二个 PRINT 陈述式企图在批次操作结束后,打印此区域变量,这时就会回传如下的错误讯息:
13.00

服务器:讯息 137,层级 15,状态 2,行 1
必须宣告变量 '@price'
第一个打印陈述式成功的执行(打印出值 13.00)。
您可能想在预存程序中使用不只一条 T-SQL 陈述式,如 BEGIN TRANSACTION、COMMIT 和 ROLLBACK 这些陈述式,操作的方法是要先将这些陈述式群组成为一个单位的交易,使用的细节请参阅 第十九章 。
使用 RETURN
 
在任何时刻使用 RETURN 关键词都可以无条件退出预存程序以回到呼叫程序,也可用于退出批次操作等等。当 RETURN 执行时,预存程序执行到该点即停止执行,并回到呼叫程序中的下一个陈述式,RETURN 也可传回整数值。
首先,让我们看一个使用 RETURN 从预存程序中退出的范例。您将修改之前的GetUnitPrice程序来检查是否提供输入值,如果没有,打印此信息给使用者并回到呼叫程序。要达成此目的,请将输入参数默认值定义为 NULL,然后检查程序中的值是否为 NULL,这表示没有输入任何值。以下是这个程序的程序代码:
USE Northwind
GO

IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = "GetUnitPrice" AND
                   type = "P")
DROP PROCEDURE GetUnitPrice
GO

CREATE PROCEDURE GetUnitPrice @prod_id int = NULL
AS
IF @prod_id IS NULL
   BEGIN
      PRINT "Please enter a product ID number"
      RETURN
   END
ELSE
   BEGIN
      SELECT  UnitPrice
      FROM    Products
      WHERE   ProductID = @prod_id
   END
GO
现在请不要输入 ProductID 值来执行GetUnitPrice并看看结果。由于呼叫程序陈述式并非该批次操作中的第一个陈述式,因次必须使用 EXECUTE 陈述式执行预存程序。程序代码如下:
PRINT "Before procedure"
EXECUTE GetUnitPrice
PRINT "After procedure returns from stored procedure"
GO
输出结果显示如下:
Before procedure
Please enter a product ID number
After procedure returns from stored procedure
由第二个 PRINT 陈述式可看出,当预存程序执行 RETURN 时,批次操作在 PRINT 陈述式处开始继续执行。
现在使用 RETURN 来传回值到呼叫程序中。传回的值必须是一个整数,常数或变量皆可。变量必须透过宣告才可在呼叫程序中使用。举例来说,当输入参数为单价少于 $100 的产品,传回值 1,否则传回 99。
CREATE PROCEDURE CheckUnitPrice @prod_id int
AS
IF (SELECT  UnitPrice
    FROM    Products
    WHERE   ProductID = @prod_id) < 100
    RETURN 1
ELSE
    RETURN 99
GO
为了呼叫预存程序并能使用传回值,在呼叫程序中宣告变量并将该变量设为预存程序的传回值,(输入参数使用 ProductID 值 66),程序代码如下:
DECLARE @return_val int
EXECUTE @return_val = CheckUnitPrice 66
IF (@return_val = 1) PRINT 'Unit price is less than $100'
GO
由于指定的产品单价为 $17,因此传回值为 1,并打印 Unit price is less than $100。当变量用于保存传回值时,记住其数据型别必须被宣告为整数,这是 RETURN 陈述式的要求。
使用 SELECT 传回值
 
在预存程序中可以使用 SELECT 陈述式传回数据,您可以从 SELECT 查询或传回变量值中传回结果集。
现在来看看几个范例。首先建立一个预存程序,命名为PrintUnitPrice,该预存程序会传回输入参数所指定的产品单价(透过 ProductID),程序代码如下:
CREATE PROCEDURE PrintUnitPrice @prod_id int
AS
SELECT  ProductID,
        UnitPrice
FROM    Products
WHERE   ProductID = @prod_id
GO
将 66 作为输入参数值呼叫该程序:
PrintUnitPrice 66
GO
结果看起来像这样:
ProductID       UnitPrice
----------      ------------
        66      17.0000
(影响 1 个数据列)
要使用 SELECT 陈述式传回变量值,请在陈述式后面接着输入变量名称。在下面的范例中,我们会重建CheckUnitPrice预存程序,传回一变量值,并指定输出标题:
USE Northwind
GO

IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = "CheckUnitPrice" AND
                   type = "P")
DROP PROCEDURE CheckUnitPrice
GO

CREATE PROCEDURE CheckUnitPrice @prod_id INT
AS
DECLARE @var1 int
IF (SELECT  UnitPrice
    FROM    Products
    WHERE   ProductID = @prod_id) > 100
    SET     @var1 = 1
ELSE
    SET     @var1 = 99
SELECT "Variable 1" = @var1
PRINT "Can add more TSQL statements here"
GO
将 66 作为输入参数值呼叫该程序:
CheckUnitPrice 66
GO
执行该预存程序的输出结果如下:
Variable    1
-------------
           99

(影响 1 个数据列)

Can add more T-SQL statements here
我们打印 Can add more T-SQL statements here 以强调使用 SELECT 传回值与使用 RETURN 传回值之间的差别。当呼叫 RETURN 时,预存程序跟着结束;当呼叫 SELECT 时,预存程序则在 SELECT 传回结果集后,继续执行。
在前面的范例中,如果没有指定输出标题,只使用SELECT @varl,输出结果将没有标题,如下所示:
(没有数据行名称)
---------------
99

(影响 1 个数据列)
使用 Enterprise Manager
 
现在让我们看看如何使用 Enterprise Manager 建立预存程序。要使用 Enterprise Manager 建立预存程序,仍然必须知道如何编写 T-SQL 陈述式,Enterprise Manager 只提供图形接口以供建立程序。现在就依照下面步骤重建InsertRows预存程序。
1. 在 Enterprise Manager 展开左侧窗口中 MyDB 数据库,选择 预存程序 数据夹以删除预存程序,所有的预存程序都显示在右侧窗格,在InsertRows预存程序(本章稍早已建立,所以应该已经存在)上右点鼠标,然后从快捷菜单中选择 删除 (也可以从快捷菜单重新命名或复制该预存程序),会出现如图 21-1 所示的 卸除对象 对话框,按 全部卸除 以删除预存程序。
 
 
图21-1 「卸除对象」对话框
2. 在 预存程序 上右点鼠标,从快捷菜单中选择 新增预存程序 ,出现的窗口如图 21-2 所示。
 
 
图21-2 「预存程序属性」窗口
3. 在 一般 卷标页的 文字 方块中,使用预存程序的名称来取代 [OWNER].[PROCEDURE NAME],在本例中,即为InsertRows,然后为预存程序输入 T-SQL。图 21-3 显示了使用 T-SQL 程序代码新增InsertRows后的预存程序属性窗口。
 
 
图21-3 用 T-SQL 程序代码增加新的预存程序
4. 按一下 检查语法 按钮,让 SQL Server 指出预存程序中的 T-SQL 语法错误,修正找到的语法错误,并反复按 语法检查 直到语法检查成功(如图 21-4 所示),按一下 确定 。
 
 
图21-4 显示语法检查成功窗口
5. 在 预存程序属性 对话框中按 确定 以建立您的预存程序,建立完后,返回 Enterprise Manager,在左侧窗格中选择 预存程序 数据夹,便可在右侧窗格中看到新建立的预存程序,如图21-5所示。
 
 
图21-5 在 Enterprise Manage 新建的的预存程序
6. 要为新的预存程序指派使用者的执行权限,请在右边窗格的预存程序名称上右点鼠标,在快捷菜单中选择 属性 ,出现 预存程序属性 窗口后,按一下 权限 呼叫 对象属性 窗口(如图 21-6 所示),在 EXEC 复选框中选择是否允许该使用者或数据库角色执行此预存程序。本范例中,我们将InsertRows预存程序的使用权限开放给三个使用者。
 
 
图21-6 「对象属性」窗口的「权限」卷标页
7. 按一下 套用/确定 以回到 预存程序属性 窗口,按一下 确定 结束。
您可以编辑已经存在的预存程序,方法为:在程序名称上按右钮,从快捷菜单中选择 属性 ,在 预存程序属性 窗口中编辑程序(同图 21-3 的对话框),使用 检查语法 按钮检查语法,确定正确无误后,按一下 套用 ,然后按一下 确定 。
您还可以利用 Enterprise Manager 管理已经存在的预存程序权限,方法为:在 Enterprise Manager 中的预存程序名称上右点鼠标,从快捷菜单中选择 所有工作 ,然后选择 管理使用权限 。在 所有工作 中,还可以选择对该预存程序 建立新的发行集 (将在本书 第二十六章 中讨论)、产生 SQL 指令码以及显示相依性。假设选择了 产生 SQL 指令码 ,SQL Server 会自动建立一个指令码档案(由您指定指令码文件名称),该指令码会包括预存程序的定义。当您想重新建立一个预存程序,就可以使用该指令文件。
使用建立预存程序精灵
 
第三种方法是使用 建立预存程序精灵 ,该精灵提供了建立预存程序所需撰写的 T-SQL 程序代码基本结构,可以帮助您插入、删除或更新数据列至数据表,但无法执行从数据表中寻找数据列的程序。
精灵允许在一个数据库中建立多个预存程序,而不需退出精灵和重新启动。但是,若要在另一个数据库中建立预存程序,就必须再次执行精灵。执行精灵时,请依照下面的步骤:
1. 在 Enterprise Manager,从工具列中选择 工具/精灵 以呼叫 选择精灵 对话框,在 数据库 中选择 建立预存程序精灵 ,如图 21-7 所示。
 
 
图21-7 「选择精灵」对话框
2. 选择 确定 叫出 建立预存程序精灵 的画面,如图 21-8 所示。
 
 
图21-8 「建立预存程序精灵」欢迎画面
3. 选择 下一步 显示 选取数据库 画面,在 数据库名称 选择欲建立预存程序的数据库。
4. 选择 下一步 进入 选取预存程序 画面(如图 21-9 所示),在这个窗口中,可以看到在这个数据库所建立的所有数据表名称,并有三个包含复选框的数据行,分别代表使用精灵所能建立的三种预存程序:插入、删除及更新数据,请选择合适的复选框。
 
 
图21-9 「选择预存程序」画面
这个范例显示了本书所使用的两个数据表,其中Bicycle_Inventory数据表被指派了两个预存程序:一个插入程序和一个更新程序。如后续的步骤所示,在实际建立这些程序之前,您可以加以修改。
________________________________________
说明
当然,一个预存程序可以执行多种类型的数据修改,但是 建立预存程序精灵 视每一个修改类型为独立的预存程序。您可以将精灵所建立的任何预存程序,用 T-SQL 程序代码变更。
________________________________________
5. 按 下一步 显示 完成建立预存程序精灵 ,如图 21-10 所示,这个画面列出所建的预存程序精灵名称及描述。
 
 
图21-10 「完成建立预存程序精灵」画面
6. 欲重新命名或编辑预存程序,在 完成建立预存程序精灵 画面中按一下 编辑 ,进入 编辑预存程序属性 窗口,如图 21-11 所示,这个画面列出此预存程序会影响的数据行,在 选取 数据行中勾选的数据行名称将会被预存程序所使用。
 
 
图21-11 「编辑预存程序属性」窗口
这个范例显示中在Bicycle_Inventory数据表中,有六个数据行会受到插入预存程序所影响,此插入预存程序已命名为insert_Bicycle_Inventory_1,每个数据行在 选取 栏里都有勾选复选框,代表六个数据行的值在预存程序执行时都需要输入,且六个数据行都会被预存程序插入值至该数据表中。
7. 要重新命名预存程序,请清除 名称 编辑方块中的名称,并用新的名称替代。
8. 要编辑预存程序,请按一下 编辑 SQL 来显示 编辑预存程序 SQL 对话框,如图 21-12 所示,在这个对话框中,可以检视预存程序的 T-SQL 程序代码,这里的 T-SQL 非常的基本。在这个范例中,当呼叫预存程序时,这里所列出的五个参数将会插入成为新资料列的值。要编辑该程序代码,只要在文字方块中输入修改设定。完成编辑后,按一下 剖析 检查语法错误,修正错误,然后按一下 确定 返回 完成建立预存程序精灵 画面。
 
 
图21-12 「编辑预存程序 SQL」对话框
9. 确定所有预存程序的程序代码无误后,按一下 完成 建立预存程序。建立完成后,别忘了为每个预存程序设定权限。(请参阅本章稍早用于介绍设定权限的 〈使用 Enterprise Manager 建立预存程序〉 一节。)
就某些方面来说,精灵并不见得非常有用。所以如果知道如何编写 T-SQL,就可以使用指令码或 Enterprise Manager 来建立预存程序。
使用 T-SQL 管理预存程序
 
现在来看看如何使用 T-SQL 命令来更改、删除和检视预存程序内容。
ALTER PROCEDURE 陈述式
 
ALTER PROCEDURE T-SQL 陈述式用于改变先前由 CREATE PROCEDURE 所建立的预存程序。使用 ALTER PROCEDURE 改变预存程序,不会变更原来预存程序所设的权限,也不会影响任何相依的预存程序或触发程序(相依程序或触发程序是呼叫预存程序的程序)。
 ALTER PROCEDURE 陈述式的语法和 CREATE PROCEDURE 类似:
ALTER PROC[EDURE] procedure_name
                  [{@parameter_name data_type}] [=default] [OUTPUT]
                  [,...,n]
AStsql_statement(s)
在 ALTER PROCEDURE 陈述式中,您必须重写整个预存程序,以达成需要的变更。举例来说,让我们重建前面例子的预存程序GetUnitPrice,并将预存程序更改为检查大于 $100 的单价,如下所示:
USE Northwind
GO

IF EXISTS (SELECT  name
           FROM    sysobjects
           WHERE   name = "GetUnitPrice" AND
                   type = "P")
DROP PROCEDURE GetUnitPrice
GO

CREATE PROCEDURE GetUnitPrice   @prod_id        int,
                                @unit_price     money OUTPUT
AS
SELECT  @unit_price = UnitPrice
FROM    Products
WHERE   ProductID = @prod_id
GO

ALTER PROCEDURE GetUnitPrice    @prod_id        int,
                                @unit_price     money OUTPUT
AS
SELECT  @unit_price = UnitPrice
FROM    Products
WHERE   ProductID = @prod_id AND
        UnitPrice > 100
GO
现在使用下列的陈述式授权使用者 DickB 该预存程序的执行权限。
GRANT EXECUTE ON GetUnitPrice TO DickB
GO
如前所述,当变更预存程序时,不会变更原预存程序的权限。现在我们更改该预存程序,选择以UnitPrice大于 $200 的数据列,代替大于 $100 的数据列,程序如下:
ALTER PROCEDURE GetUnitPrice    @prod_id        int,
                                @unit_price     money OUTPUT
AS
SELECT  @unit_price = UnitPrice
FROM    Products
WHERE   ProductID = @prod_id AND
        UnitPrice > 200
GO
执行 ALTER PROCEDURE 陈述式后,使用者 DickB 仍保留对该预存程序的执行权限。
DROP PROCEDURE 陈述式
 
DROP PROCEDURE T-SQL陈述式简单的说,就是用以删除已经存在的预存程序;预存程序在删除后不能被复原,如果要重新建立已经删除的预存程序,就要使用 CREATE PROCEDURE 陈述式重建。删除预存程序将遗失所有权限设定,重新建立之后必须重新授权。下面是使用 DROP PROCEDURE 来删除GetUnitPrice预存程序的范例:
USE Northwind
GO

DROP PROCEDURE GetUnitPrice
GO
________________________________________
说明
要删除预存程序,必须使用该预存程序所属的数据库。请记住当您使用数据库时,使用 USE 陈述式并且输入数据库名称即可。
________________________________________
sp_helptext预存程序
 
sp_helptext系统预存程序让您检视预存过程定义,以及建立预存程序的陈述式(也可用于打印触发程序、检视表、规则或默认值的定义)。当您想要快速使用 ISQL、OSQL 或 SQL Query Analyzer 呼叫出程序的定义时,sp_helptext就很有用。您也可以将输出指定到一个档案内,当需要编辑或重建预存程序时,就可叫出档案直接修改。要使用sp_helptext,必须利用使用者自订预存程序(或其它对象名称)的名称作为参数。举例来说,要检视之前建立InsertRows预存程序的陈述式,请使用以下命令:
USE MyDB
GO
sp_helptext InsertRows
GO
输出如下:
Text
------------------------------------------------
CREATE PROCEDURE InsertRows @start_value int
AS
DECLARE @loop_counter   int,
        @start_val      int
SET     @start_val = @start_value - 1
SET     @loop_counter = 0
WHILE (@loop_counter < 5)
   BEGIN
      INSERT INTO mytable VALUES (@start_val + 1, 'new row')
      PRINT (@start_val)
      SET @start_val  = @start_val + 1
      SET @loop_counter       = @loop_counter + 1
   END
本章总结
 
在本章中,您学到了系统预存程序与使用者自订预存程序的使用方式,以及如何使用 T-SQL 程序代码、Enterprise Manager 和建立预存程序精灵,建立使用者自订的预存程序;此外,您还学到如何使用参数和变量,以及如何执行预存程序,并看到了用于更改、删除和检视预存过程定义的 T-SQL 陈述式。 第二十二章 将学习触发程序,触发程序是一种特殊的预存程序,可在特定条件下自动执行。




20. 认识进阶的 T-SQL
INSERT 陈述式
UPDATE 陈述式
DELETE 陈述式
程序设计关键词
本章总结
本章将详细讨论前面章节所使用过用来修改数据的T-SQL陈述式,加上一些可用来控制程序设计流程的T-SQL关键词。这些陈述式及关键词可用于任何可以使用T-SQL的地方,如使用在指令行、指令码、预存程序、批次文件和应用程序中。我们会特别学习有关数据处理的陈述式,如INSERT、UPDATE和DELETE(这些陈述式在 第十三章 曾经提到过),以及程序结构,如IF、WHILE和CASE。
首先我们为范例建立一个数据表,命名为items(请将该数据表建立在MyDB数据库内),以下为建立items数据表的T-SQL命令:
USE MyDB
GO
CREATE TABLE items
(
item_category   CHAR(20)        NOT NULL,
item_id         SMALLINT        NOT NULL,
price           SMALLMONEY      NULL,
item_desc       VARCHAR(30)     DEFAULT 'No desc'
)
GO
item_id数据行适合设成IDENTITY属性(请参阅 第十章的〈增加IDENTITY属性〉 。但由于识别数据行不允许直接插入值,因此这里不使用IDENTITY;这样才可以更有弹性的使用包含INSERT陈述式的范例。
INSERT陈述式
 
在 十三章 曾介绍过INSERT陈述式,可以用来新增数据列至数据表或检视表。以下为INSERT陈述式的基本语法:
INSERT [INTO] table_name [(column_list)] VALUES
    expression | derived_table
INTO关键词和 数据行清单(column_list) 参数可依需要而设定。 数据行清单 参数指定了要插入值的数据行,这些值和表达式中所列的值按顺序对应(也可以只包含值的清单)。
插入资料列
 
下面范例示范如何插入数据列至items数据表。
INSERT INTO items
    (item_category, item_id, price, item_desc)
VALUES ('health food', 1, 4.00, 'tofu 6 oz.')
GO
由于已经替数据表中的每个数据行都指定了一个值,而且依照数据列在数据表中定义的顺序列出对应的值,因此我们也可以不必使用 数据行清单 。但是如果值不是依数据行的顺序排列,输入的数据就可能不正确,或是收到错误讯息。举例来说,试着执行以下的陈述式,就会收到错误讯息:
INSERT INTO items
VALUES (1, 'health food', 4.00, 'tofu 6 oz.')
GO
服务器:讯息245,层级16,状态1,行1
将varchar数值 'health food' 转换成数据型别为smallint的数据行语法错
误。
由于值所放置的顺序不正确,因此数据列并没有被插入,并传回错误讯息。我们尝试把item_id插入item_category数据行,item_category插入item_id数据行(两个数据输入的顺序颠倒),两个不同数据型别的数据并不兼容,当然,如果两个数据行的型别是兼容的,就算数值不同,数据也会被插入,不过数据虽然被插入,却是不正确的数据。
要看看插入的列在数据表中如何显示,使用下面的SELECT陈述式查询资料表,以选择所有的列。
SELECT * from items
GO
会看到以下的结果集:
item_category   item_id price   item_desc
--------------  -------------   ----------
health food     1       4.00    tofu 6 oz.
当建立items数据表时,price数据行定义为允许NULL值,item_desc(描述)数据行的默认值为No desc。如果INSERT陈述式中没有替price数据行指定一个值,新数据列中将插入NULL;如果item_desc数据行没有指定一个值,将插入默认值No desc。
省略资料行值
 
在前面INSERT陈述式范例中,由于price数据行和item_desc数据行设有默认值,所以可以省略数据行的值和名称。如果要省略数据行的值,必须为其它在 数据行清单 的数据行指定参数,否则,列出的值将依照数据表中数据行定义的顺序,分配给各数据行。
举例来说,我们照下面这样输入:在 数据行清单 中少输入了一行价钱,也没有为 数据行清单 指定值。
INSERT INTO items
VALUES ('junk food', 2, 'fried pork skins')
GO
SQL Server会试着把item_desc(值清单中的第三个值)提供的值(fried pork skins)插入price数据行(数据表中的第三字段)。由于price数据行为smallmoney数据型别,fried pork skins是char数据型别,两个不兼容的数据型别,就会产生如下的错误讯息:
服务器:讯息213,层级16,状态4,行1
插入错误:数据行名称或提供的数值数量与数据表定义不相符。
试想如果fried pork skins的数据型别和price数据行兼容,数据就会被不正确的插入,也影响了整个数据表的一致性与正确性。
记住插入数据表或检视表的值的数据型别必须和字段定义的数据型别兼容。还有,如果插入的数据列违反了规则或条件约束,会产生错误讯息,数据列也不会被插入。
为了避免不兼容数据型别的错误发生,指定 数据行清单 以符合应当被插入的值,如下所示:
INSERT INTO items
    (item_category, item_id, item_desc)
VALUES ('junk food', 2, 'fried pork skins')
GO
由于没有指定价格,price数据行将插入NULL值。执行下面的SELECT陈述式:
SELECT * FROM items
应该会出现下述的结果集,结果集中包含已插入的两个数据列,注意price数据列中的NULL。
item_category   item_id price   item_desc
--------------  --------------  -----------------
health food     1       4.00    tofu 6 oz.
junk food       2       NULL    fried pork skins
现在增加另一数据列,不要指定price数据行或item_desc数据行的值,如下所示:
INSERT INTO items
    (item_category, item_id)
VALUES ('toy', 3)
GO
使用下面的查询就可以得到该列的结果集:
SELECT * FROM items WHERE item_id = 3
结果集如下所示:
item_category   item_id price   item_desc
--------------  --------------  ------------
toys    3       NULL    No desc
注意price数据行中的NULL和item_desc资料列中的No desc。这些值可用稍后本章将介绍的UPDATE陈述式变更。
有四种类型的数据行,在没有指定值时,SQL Server会自动提供值给该数据行:分别是 允许NULL值 、 设定默认值 、 IDENTITY属性 和 时间戳记(timestamp) 的数据行。之前讨论过允许NULL值的数据行和含默认值的数据行,若没有指定值会产生的情形(在 第十章 讨论过)。大部分的情况下,是不能手动插入数据值到这两种类型的数据行中。
________________________________________
说明
在数据表中执行INSERT操作时要谨慎。请确定插入的数据正确地放入应当插入的数据行。确定测试了所有的T-SQL程序代码后,再存取或修改数据。
________________________________________
从另一数据表中新增数据列
 
您可以从数据表插入数据列到另一个资料表中。这可以透过在INSERT陈述式中使用衍生资料表,或在传回数据列的预存程序中使用EXECUTE子句来完成。
________________________________________
说明
衍生数据表(Derived Table)即为来自另一个T-SQL陈述式FROM子句中的SELECT陈述式结果集,在 第十四章 中会讨论到衍生数据表。
________________________________________
现在来示范如何使用衍生数据表插入数据。首先建立数据表,命名为two_newest_items,并将item资料表中的两笔数据列插入two_newest_items,以下是建立新数据表所使用的CREATE TABLE陈述式:
CREATE TABLE two_newest_items
(
item_id    SMALLINT     NOT NULL,
item_desc  VARCHAR(30)  DEFAULT 'no desc'
)
GO
要从items数据表将item_id和item_desc资料行中最新的值插入two_newest_items数据表,请使用下面的INSERT陈述式:
INSERT INTO two_newest_items
    (item_id, item_desc)
SELECT TOP 2 item_id, item_desc FROM items
ORDER BY item_id DESC
GO
请注意这里使用的是SELECT陈述式,而不是列在INSERT陈述式的值清单。SELECT陈述式从一个已存在的数据表中传回数据,传回的数据当成值清单。另外,注意在SELECT陈述式上并没有加括号,因为括号将造成传回语法错误。
要查询新数据表中所有数据列,可使用下列程序代码:
SELECT * FROM two_newest_items
所显示的结果集如下:
item_id item_desc
-------------------------
3       No desc
2       fried pork skins
请注意,我们在这里的INSERT陈述式中使用ORDER BY子句,使item_id的数据列递减排序。
如果我们将前面的SELECT陈述式建立为预存程序,使用EXECUTE陈述式加上预存程序名称,也可以得到同样的结果(预存程序将会在 第二十一章 介绍)。操作的方法为,首先使用DELETE陈述式删除two_newest_items数据表中现存的所有数据列。(详细细节请参阅本章稍后的 〈DELETE陈述式〉 。)然后建立一个预存程序,命名top_two,并用EXECUTE陈述式插入两个新数据列到two_newest_items数据表。操作的T-SQL陈述式为:
DELETE FROM two_newest_items
GO
CREATE PROCEDURE top_two
AS
SELECT TOP 2 item_id, item_desc FROM items
ORDER BY item_id DESC
GO
INSERT INTO two_newest_items
    (item_id, item_desc)
EXECUTE top_two
GO
现在可以看到,我们已经使用top_two预存程序成功地插入两个新的数据列。
________________________________________
相关信息
INSERT陈述式可以用于指定数据表提示(Table Hints)。要详细了解可以和INSERT陈述式一起使用的数据表提示,请使用《在线丛书》,在搜寻标签页中输入 锁定提示 ,选择 锁定提示 主题。
________________________________________
UPDATE陈述式
 
UPDATE陈述式用于修改或更新存在的数据,基本语法如下:
UPDATEtable_nameSETcolumn_name = expression
    [FROMtable_source] WHERE search_condition
更新数据列
 
本范例将使用之前的items范例数据表,首先更新之前没有输入价格的junk food数据列。要识别数据列,将搜寻条件指定为fried pork skins,用下列陈述式更新价格至 $2元:
UPDATE items SET price = 2.00
WHERE item_desc = 'fried pork skins'
GO
然后使用查询选出junk food数据列:
SELECT * FROM items
WHERE item_desc = 'fried pork skins'
GO
junk food数据列输出显示如下,原来的NULL值被2.00所替代:
item_category   item_id price           item_desc
--------------  ----------------------- ------------
junk food       2       2.00    fried pork skins
您也可以使用以下的陈述式将价格增加10%:
UPDATE items SET price = price * 1.10
WHERE item_desc = 'fried pork skins'
GO
现在如果选择junk food数据列,价格已变更至 $2.20($2乘以1.10的结果);其它项目的价格则维持不变。
使用UPDATE陈述式可以更新一个以上的资料列。举例来说,可以将所有数据列的价格都增加10%,其陈述式如下:
UPDATE items SET price = price * 1.10
GO
得到的输出结果如下:
item_category   item_id price   item_desc
--------------- --------------- -----------------
health food     1       4.40    tofu 6 oz.
junk food       2       2.42    fried pork skins
toys            3       NULL    No desc
价格设为NULL的数据列不会变动(因为NULL* 1.10还是等于NULL),这样的执行方式是可以接受的,不会产生错误讯息。
使用FROM子句
 
UPDATE陈述式可利用FROM子句指定更新操作中的数据来源,数据来源清单可以包含数据表名称、检视表名称、数据列及函数、衍生数据表和联结数据表,甚至更新中的数据表也可以当成数据表来源。以下是范例,首先利用CREATE TABLE陈述式建立一个新的数据表,命名为tax,再用INSERT陈述式插入新的数据列,在tax_percent数据行中将值设为5.25。
CREATE TABLE tax
(
tax_percent   real            NOT NULL,
change_date   smalldatetime   DEFAULT getdate( )
)
GO
INSERT INTO tax
    (tax_percent) VALUES (5.25)
GO
由于没有设定日期和时间,change_date数据行会使用默认值,由GETDATE函数得到目前的日期和时间。
现在在item数据表中新增一个新的数据行,命名为price_with_tax,并允许NULL值,陈述式如下:
ALTER TABLE items
ADD price_with_tax smallmoney NULL
GO
接下来要更新所有price_with_tax数据行,这个数据行的数据是由items.price * tax.tax_percent运算而来。使用UPDATE陈述式和FROM子句如下:
UPDATE items
SET price_with_tax = i.price +
    (i.price * t.tax_percent / 100)
FROM items i, tax t
GO
在price数据行有数值的数据列,在price_with_tax数据行也会出现运算后的数值;如果原price数据行的数据为NULL,则相对应的price_with_tax也会出现NULL(NULL乘以任何值还是NULL),运算后的结果集如下(结果也包含所有先前对数据所做的修改):
item_category   item_id price   item_desc       price_with_tax
--------------  ------- ------  --------------- ------------------
health food     1       4.40    tofu 6 oz       4.63
junk food       2       2.42    fried pork skin 2.55
toys            3       NULL    No desc         NULL
如果在数据表中新增记录,可以考虑执行之前的UPDATE陈述式,但这样会再次更新price_with_tax数据行,浪费程序时间。要避免这种情况,可以使用UPDATE陈述式的WHERE子句,让SQL Server更新price_with_tax中只含有NULL值的数据行。
UPDATE items
SET price_with_tax = i.price +
    (i.price * t.tax_percent / 100)
FROM items i, tax t
WHERE i.price_with_tax IS NULL
GO
UPDATE陈述式非常适合当作触发程序,当插入一个值到price数据行时,便会执行。触发程序是一种特殊的预存程序,在某一特定的条件下会自动执行。触发程序将在 第二十二章 中加以讨论。
使用衍生数据表
 
使用UPDATE陈述式的另一个方法是在FROM子句中附带一个衍生数据表或子查询。然后衍生数据表就可以当成外部UPDATE的输入。使用范例,我们将在子查询中使用two_newest_items数据表,在外部UPDATE陈述式中使用items数据表。我们想要更新items数据表中的两列数据,以使price_with_tax数据行储存NULL值,可以利用查询two_newest_items数据表,即可找出数据列中需要更新的item_id值:
UPDATE items
SET price_with_tax = NULL
FROM (SELECT item_id FROM two_newest_items) AS t1
WHERE items.item_id = t1.item_id
GO
SELECT陈述式当成子查询,其结果会放入命名为t1的暂存衍生数据表中,此数据表会被WHERE子句当成搜寻条件。子查询的结果产生item_id的2和3两个值,只要在item_id数据行中有2或3这两个值,就会被影响。在item_id值为3的资料列,因为对应的price_with_tax数据行已有NULL值,故不会再改变;而在item_id值为2的数据列则更新为NULL值。结果集如下:
item_category  item_id price   item_desc        price_with_tax
-------------- ------- -----   ---------------  --------------
health food    1       4.40    tofu 6 oz.       2.30
junk food      2       2.42    fried pork skins NULL
toys           3       NULL    No desc          NULL
DELETE陈述式
 
DELETE陈述式用于从数据表或检视表中移除(删除)一个或多个数据列。DELETE不影响数据表定义;只是从数据表中删除数据列。DELETE陈述式的基本语法如下:
DELETE [FROM]table_name|view_name
    [FROMtable_sources] WHEREsearch_condition
第一个和第二个FROM关键词可视需要使用。在第二个FROM子句中,数据表来源中的数据列不会被删除,但会从DELETE后指定的table_name或view_name中被删除。
删除个别数据列
 
在DELETE中使用WHERE子句,可以指定从资料表中删除特定的数据列。举例来说,要从items数据表中删除item_category中toy这个数据列,执行下面的叙述:
DELETE FROM items
WHERE item_category = 'toy'
GO
该陈述式从items资料表中删掉了一列。
使用一个或多个数据表来源的第二个FROM子句,可指定其它数据表或检视表,供WHERE搜寻条件使用。例如,要从items数据表中删除对应于two_newest_items数据表中的数据列,可执行下面的陈述式:
DELETE items
FROM two_newest_items
WHERE items.item_id = two_newest_items.item_id
GO
请注意,在这个陈述式中,two_newest_items数据表中的item_id数据列含有2和3的值,而items数据表中的item_id数据列则含有1和2的值,所以2就被删除(因为符合搜寻条件)。在two_newest_items数据表(数据来源)的两个数据列则不受影响。
删除所有数据列
 
要删除数据表中的所有数据列,可利用DELETE陈述式。下面的DELETE陈述式将删除two_newest_items数据表中的所有数据列:
DELETE FROM two_newest_items
GO
现在two_newest_items数据表是一个空的数据表,即不包含数据列的数据表。如果想删除数据表定义,请使用 第十五章 说明的DROP TABLE指令:
DROP TABLE two_newest_items
GO
________________________________________
相关信息
在《在线丛书》中可找到更多使用DELETE的方法,例如利用联结数据表作为数据表来源,以及使用数据表和查询提示,请在《在线丛书》索引中查阅DELETE并选择相关的次主题。
________________________________________
程序设计关键词
 
T-SQL陈述式中有几个有用的程序设计结构关键词,能用来控制程序流程。这些结构可用于批处理(一次执行一组T-SQL陈述式)、预存程序、指令码和特别的查询(本节范例会使用pubs数据库)。
IF...ELSE
 
IF...ELSE结构利用条件以决定将执行那一条T-SQL陈述式,语法如下:
IFBoolean_expression
T-SQL_statement | block_of_statements
[ELSET-SQL_statement | block_of_statements]
布尔表达式(Boolean Expression)指的是传回TRUE或FALSE的表达式。如果IF子句中的表达式传回TRUE,陈述式将执行,ELSE子句及其叙述则不执行;如果表达式传回FALSE,就会只执行ELSE关键词后的叙述。 陈述式区块(block_of_statements) 代表一个以上的T-SQL陈述式。使用陈述式区块时,无论该陈述式区块在IF子句中、ELSE子句中或是两者都有,都必须用关键词BEGIN和END来指定区块的开始和结束。
您也可以使用没有ELSE子句的IF子句。现在我们先来看看只使用IF子句的范例,下面的程序代码将检查表达式,如果表达式传回TRUE,将执行接下来的PRINT陈述式:
IF (SELECT ytd_sales FROM titles
    WHERE title_id = 'PC1035') > 5000
PRINT 'year-to-date sales are
    greater than $5,000 for PC1035.'
GO
因为title_id = 'PC1035'数据列ytd_sales的值是8780(大于5000),因此IF表达式将计算为TRUE,并执行PRINT陈述式,将「Year-to-date sales are greater than $5,000 for PC1035」打印在屏幕上。
现在将一个ELSE子句新增到上面的范例中,并将> 5000变为> 9000。IF...ELSE显示如下:
IF (SELECT ytd_sales FROM titles
    WHERE title_id = 'PC1035') > 9000
PRINT 'yeartodate sales are
    greater than $9,000 for PC1035.'
ELSE
PRINT 'yeartodate sales are
    less than $9,000 for PC1035.'
GO
在本范例中,由于IF表达式传回FALSE。ELSE子句后的打印陈述式将被执行。
让我们更进一步扩展以上的范例,并在IF和ELSE子句中新增陈述式区块。根据IF条件传回的结果,打印讯息后执行查询,下面是范例程序代码:
IF (SELECT ytd_sales FROM titles WHERE title_id = 'PC1035') > 9000
BEGIN
    PRINT 'year-to-date sales are
        greater than $9,000 for PC1035.'
    SELECT ytd_sales FROM titles
        WHERE title_id = 'PC1035'
END
ELSE    -- ytd_sales必须小与或等于9000.
BEGIN
        PRINT 'year-to-date sales are
            less than or equal to $9,000 for PC1035.'
        SELECT price FROM titles
            WHERE title_id = 'PC1035'
END
GO
IF计算式结果是FALSE,所以会执行ELSE子句中BEGIN和END之间的叙述:执行PRINT后接着执行SELECT陈述式,显示书价为 $22.95。
您也可以在IF子句或ELSE子句后使用巢状的IF陈述式。举例来说,可执行下面的程序代码,使用巢状的IF...ELSE陈述式找出ytd_sales平均值的范围:
IF (SELECT avg(ytd_sales) FROM titles) < 10000
    IF (SELECT avg(ytd_sales) FROM titles) < 5000
        IF (SELECT avg(ytd_sales) FROM titles) < 2000
            PRINT 'Average year-to-date sales are
            less than $2,000.'
        ELSE
        PRINT 'Average year-to-date_ sales are
            between $2,000 and $4,999.'
        ELSE
        PRINT 'Average year-to-date sales are
            between $5,000 and $9,999.'
ELSE   
PRINT 'Average year-to-date sales are greater
        than $9,999.'
GO
当您执行该程序代码时,将会看到两次这样的讯息:「警告:汇总(aggregate)或其它SET操作已消除Null值。」该讯息表示数据表计算平均数时,在ytd_sales数据行的NULL值未被使用,也未被当成值来计算。由于平均值是 $6,090,该程序代码所得到最后结果是「Average year-to-date sales are between $5,000 and $9,999.」。请注意,当使用IF陈述式时,很容易就把IF应该和哪个ELSE为一组混淆,或者有了IF但忘了指示ELSE,所以用TAB键(如上所示)是不错的办法。
WHILE
 
该条件判断式是设定SQL陈述式或陈述式区块重复执行的条件。只要指定条件为TRUE,陈述式会一直重复执行。这就是所谓的WHILE循环(Loop),因为WHILE结构中的程序代码在循环中重复。语法显示如下:
WHILEBoolean_expression
SQL_statement | block_of_statements
[BREAK]SQL_statement | block_of_statements
[CONTINUE]
同上述的IF...ELSE,使用BEGIN和END来指定WHILE循环中陈述式的起始和结束。BREAK关键词则将导致从WHILE循环中跳出,然后接着执行WHILE循环结束后的陈述式。如果一个WHILE循环与另一个WHILE循环是巢状结构,BREAK关键词只会从被包含的WHILE循环中跳出,继续执行该循环外所有的的陈述式和循环。CONTINUE关键词指定WHILE循环重新执行BEGIN和END之间的陈述式,忽略CONTINUE之后的其它陈述式。
现在使用简单的WHILE循环重复执行UPDATE陈述式。WHILE循环的检测条件为:royalty资料行的平均值是否少于20。如果检测传回TRUE,所有royalty数据列的值都会增加5%。接着再次检测WHILE条件,重复更新直到royalty字段的平均值为20或更多。程序代码如下:
WHILE (SELECT AVG(royalty) FROM roysched) < 20
UPDATE roysched SET royalty = royalty * 1.05
GO
由于royalty数据行原来的平均值是15,因此在平均值达到20前,WHILE循环共执行了21次,直到检测条件回传值为FALSE时才停止。
现在看一个在WHILE循环中使用BREAK、CONTINUE、BEGIN和END的范例。我们将执行循环直到royalty的平均值达到25。但如果在循环中,royalty的最大值超过27,将中断循环,并在WHILE循环结束后加一个SELECT陈述式。下面是T-SQL程序代码:
WHILE (SELECT AVG(royalty) FROM roysched) < 25
BEGIN
UPDATE roysched SET royalty = royalty * 1.05
IF (SELECT MAX(royalty) FROM roysched) > 27
BREAK
ELSE
CONTINUE
END
SELECT MAX(royalty) AS "MAX royalty" FROM roysched
GO
数据表中已经存在的royalty值大于27,因此只执行一次循环,而royalty的平均值小于25%,因此UPDATE执行一次;接着IF陈述式检测并传回TRUE,所以执行BREAK,跳出WHILE循环;最后执行END关键词后的陈述式,也就是SELECT陈述式。
您还能使用巢状的WHILE循环,但记得BREAK或CONTINUE关键词只应用于呼叫它们的循环,而不是外部的WHILE循环。
CASE
 
CASE关键词用来评估各种条件的清单,并且传回多种可能的结果表达式其中之一,最常见的用法是用来取代程序代码,或是使用具可读性的数值(缩写值),或者用来分类值,本节的范例将加以介绍。CASE被分为两种格式:简单(simple)格式和搜寻(searched)格式。简单格式会使用CASE之后的表达式,与一组在WHEN之后的表达式做比较,以决定其结果;搜寻格式则评估一组布尔表达式为TRUE或FALSE,以决定其结果。以下为简单格式的语法:
CASE input_expression
    WHEN when_expression THEN result_expression
    [WHEN when_expression THEN result_expression...n]
    [ELSE else_result_expression]
END
when_expression和input_expression会依其在CASE子句中的排列顺序进行比较,如果相对应的when_expression等于input_expression,将传回result_expression值。如果没有对应的值,将传回指定的else_result_expression的值。如果没有指定else_result_expression,则传回NULL。注意在简单格式CASE子句中,input_expression值和when_expression值的数据型别必须相同,或是数据型别之间允许隐含转换。
下面的范例在SELECT陈述式中使用简单格式的CASE子句。Sales数据表的payterms数据行包含了Net 30、Net 60、On invoice或None。这个T-SQL陈述式允许使用替代值(易于了解)以显示payterms数据行:
SELECT 'Payment Terms' =
CASE payterms
    WHEN 'Net 30' THEN 'Payable 30 days
        after invoice'
    WHEN 'Net 60' THEN 'Payable 60 days
        after invoice'
    WHEN 'On invoice' THEN 'Payable upon
        receipt of invoice'
    ELSE 'None'
    END,
title_id
FROM sales
ORDER BY payterms
GO
CASE子句会检测payterms数据行中,被SELECT陈述式中所指定每个数据列的值。当when_expression值等于payterms值,传回result_expression的值。来自CASE子句的结果显示在结果集中的Payment Terms资料行中,如下所示:
Payment Terms                   title_id
------------------------------- -----------
Payable 30 days after invoice   PC8888
Payable 30 days after invoice   TC3218
Payable 30 days after invoice   TC4203
Payable 30 days after invoice   TC7777
Payable 30 days after invoice   PS2091
Payable 30 days after invoice   MC3021
Payable 30 days after invoice   BU1111
Payable 30 days after invoice   PC1035
Payable 60 days after invoice   BU1032
Payable 60 days after invoice   PS2091
Payable 60 days after invoice   PS2091
Payable 60 days after invoice   PS1372
Payable 60 days after invoice   PS2106
Payable 60 days after invoice   PS3333
Payable 60 days after invoice   PS7777
Payable 60 days after invoice   BU7832
Payable 60 days after invoice   MC2222
Payable upon receipt of invoice PS2091
Payable upon receipt of invoice BU2075
Payable upon receipt of invoice MC3021
Payable upon receipt of invoice BU1032

(影响21个数据列)
现在我们来看看搜寻格式的CASE子句,语法如下:
CASE
   WHENBoolean_expressionTHENresult_expression
   [WHENBoolean_expressionTHENresult_expression...n]
   [ELSEelse_result_expression]
END
简单格式与搜寻格式的CASE子句其区别在于:搜寻格式的CASE子句在CASE关键词后没有input_expression值,而在WHEN关键词后以Boolean表达式检测TRUE或FALSE,并不像简单格式比较表达式之间是否相等。搜寻格式的CASE子句依照各个表达式排列的顺序检测Boolean_expression值,并传回评估为TRUE的第一个result_expression值。
举例来说,下面的SELECT陈述式中的CASE子句将检测每一个数据列的price值,并且以书的价格范围为标准,比较数据列中的price值,传回一个字符串:
SELECT 'Price Range' =
    CASE
       WHEN price BETWEEN .01 AND 10.00
           THEN 'Inexpensive: $10.00 or less'
       WHEN price BETWEEN 10.01 AND 20.00
           THEN 'Moderate: $10.01 to $20.00'
       WHEN price BETWEEN 20.01 AND 30.00
           THEN 'Semi-expensive: $20.01 to $30.00'
       WHEN price BETWEEN 30.01 AND 50.00
           THEN 'Expensive: $30.01 to $50.00'
       WHEN price IS NULL
           THEN 'No price listed'
       ELSE 'Very expensive!'
    END,
title_id
FROM titles
ORDER BY price
GO
结果集显示如下:
Price Range                     title_id
------------------------------- ----------
No price listed                 MC3026
No price listed                 PC9999
Inexpensive: $10 or less        MC3021
Inexpensive: $10 or less        BU2075
Inexpensive: $10 or less        PS2106
Inexpensive: $10 or less        PS7777
Moderate: $10.01 to $20         PS2091
Moderate: $10.01 to $20         BU1111
Moderate: $10.01 to $20         TC4203
Moderate: $10.01 to $20         TC7777
Moderate: $10.01 to $20         BU1032
Moderate: $10.01 to $20         BU7832
Moderate: $10.01 to $20         MC2222
Moderate: $10.01 to $20         PS3333
Moderate: $10.01 to $20         PC8888
Semiexpensive: $20.01 to $30    TC3218
Semiexpensive: $20.01 to $30    PS1372
Semiexpensive: $20.01 to $30    PC1035

(影响18个数据列)
________________________________________
说明
以上两个CASE子句范例中,由于整个CASE子句是SELECT子句中 数据行清单 的一部份,所以我们在END关键词后插入了逗号后,才加入title_id数据行。换句话说,整个CASE子句在数据行清单中只是一个项目。这是CASE关键词最常被使用的方法。
________________________________________
其它关键词
 
以下为其它可用于控制程序流程的T-SQL关键词:
•   GOTO label:当GOTO中定义了某label时,导向处理程序直接由该label后开始继续处理。
 
•   RETURN :无条件从查询或程序中退出。
 
•   WAITFOR :为陈述式的执行设定延迟或指定时间。
 
________________________________________
相关信息
要详细了解如何使用这些关键词,可在《在线丛书》索引中查阅GOTO、RETURN和WAITFOR,检视对话框中所列的主题。
________________________________________
本章总结
 
在本章中,您学到了使用INSERT、UPDATE和DELETE的T-SQL陈述式,以及用来控制程序流程的关键词IF、ELSE、WHILE、BEGIN、END和CASE。 第二十一章 将学习如何建立预存程序,配合使用这些陈述式和结构。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值