hudan's blog

    学海无涯,回头是岸

博客园 首页 新随笔 联系 订阅 管理
  23 Posts :: 0 Stories :: 42 Comments :: 0 Trackbacks

公告

来源:
http://www.microsoft.com/china/sql/using/tips/administration/default.asp

在SQL Server所在的计算机上运行病毒扫描软件
 
更新日期: 2002年9月3日  
 
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:如果我需要在运行有SQL Server的机器上运行病毒扫描软件,怎样做才不会影响性能?

答:该问题的答案取决于您希望运行的病毒扫描软件的类型。目前有三种类型的病毒扫描软件——主动病毒扫描、病毒清除及漏洞扫描。

主动病毒扫描软件
我们推荐将主动病毒扫描用于以下SQL Server使用场合:

运行在Internet上。
读取并执行来自其他服务器的文件。
运行HTTP服务器,如Microsoft Internet Information Services (IIS)或Apache。如果您使用XML for SQL Server (SQLXML)经由IIS上的HTTP访问SQL Server,则它适用于您的操作环境。
主机文件共享。
使用SQL Mail处理传入和传出的电子邮件。
主要的性能开销为打开和关闭文件。尽管主动病毒扫描可能会在重负荷机器上导致明显的性能损失,但出于安全性的考虑,它仍是推荐使用的病毒扫描软件。

病毒清除软件
如果病毒清除软件不得不扫描SQL Server数据库文件,SQL Server将因为I/O子系统大量的读操作而导致性能降低,尤其是在文件数量较多的服务器上。如果该软件打开某个文件进行扫描,而您同时打开了SQL Server,该软件将把数据库标记为“可疑”,从而使数据库服务中断。

值得注意的是,这一类型的软件在病毒已经侵入您的硬盘后才生效。因此,您所在的机构最好通过采用可靠的安全操作,防患于未然。

漏洞扫描软件
漏洞扫描软件主要面向HTTP服务器。这种类型的病毒扫描可以很好地清除潜在的漏洞。在使用漏洞扫描软件时,Microsoft没有注意到任何SQL Server性能损失。

—Microsoft SQL Server开发团队
--------------------------------------------------------------------------

将列更新从一个表传递到另一个表
更新日期: 2002年10月28日 

本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:怎样在一个UPDATE语句中使用表B的三个列更新表A中的三个列?

答:对这个问题,您可以使用强大的关系代数。本页中的代码说明了如何组合使用FROM子句和JOIN操作,以达到用其他表中数据更新指定列的目的。在设计关系表达式时,您需要决定是否需要单一行匹配多个行(一对多关系),或者需要多个行匹配被联接表中的单一行以更新所有行(多对一关系)。

在一对多关系中,SQL Server始终使用它找到的最后一行更新数据。但是,您无法控制最后一行所在的位置。在多处理器的计算机上,查询可能是同步进行的,相同的查询最后一行的位置可能会不同。因此,Microsoft建议尽量不要使用一对多关系。

如果待更新的表与FROM子句中的表相同,并且FROM子句只包含对该表的一个引用,别名可能未被指定。如果待更新的表在FROM子句中出现了多次,只有该表的一个引用可以省略表的别名,对该表的所有其他引用必须包含一个表别名。

USE tempdb
GO
CREATE TABLE #t1 (c1 int NOT NULL, c2 char(5), c3 char(5),
 c4 char(5))
GO
CREATE TABLE #t2 (c1 int NOT NULL, c2 char(5), c3 char(5),
 c4 char(5))
GO


--数据赋值
INSERT #t1 values (1,'hello','there','fred')
INSERT #t2 values (1,'how','are','you?')


--更新数据
UPDATE #t1 SET #t1.c2 = #t2.c2, #t1.c3 = #t2.c3,
 #t1.c4 = #t2.c4
FROM #t2
WHERE #t1.c1 = #t2.c1


--检查结果
SELECT * FROM #t1

—Microsoft SQL Server开发团队

---------------------------------------------------------------------------
回滚事务日志文件中的事务
  
更新日期: 2002年7月22日  
 
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:怎样使用Transact-SQL回滚某个位于事务日志文件中的事务(例如,ID 0000:0010a183)?

答:出于预防数据错误的考虑,SQL Server并不支持个别事务的回滚。举例来说,假设两个事务T1和T2使用现金余额域。T1添加了500美金,T2使用更新后的值进行了某个操作。如果回滚T1,则T2可能是错误的。但是,您可以使用时间戳或事务日志标记将日志恢复至预定义的标记或时间点。以下两个例子说明了如何使用SQL Server 2000语法。

例1:使用时间戳将日志进行时点恢复
使用以前的完全备份恢复数据库,并使其为日志恢复做好准备。

RESTORE DATABASE pubs FROM DISK = N'C:\Backups\Fullbackup.bak' WITH NORECOVERY

现在您可以将日志前滚到合适的时间点,并使数据库可供使用。请注意,STOPAT在数据库正在执行大容量日志时禁止执行。

RESTORE LOG pubs FROM DISK=N'C:\Backups\Logbackup.bak' WITH RECOVERY,STOPAT='02/11/2002 17:35:00'

例2:使用数据库标记将日志恢复到预定义时间点的语句
在事务日志中置入一个标记。请注意,被标记的事务至少须提交一个更新,以标记该日志。

BEGIN TRAN MyMark WITH MARK
UPDATE pubs.dbo.LastLogMark SET MarkTime = GETDATE()
COMMIT TRAN MyMark

按照您常用的方法备份事务日志。

BACKUP LOG pubs TO DISK='C:\Backups\Fullbackup.bak' WITH INIT

现在您可以将数据库恢复至日志标记点。首先恢复数据库,并使其为接受日志恢复做好准备。

RESTORE DATABASE pubs FROM DISK=N'C:\Backups\Fullbackup.bak' WITH NORECOVERY

现在将日志恢复至包含该标记的时间点,并使其可供使用。请注意,STOPAT在数据库正在执行大容量日志时禁止执行。

RESTORE LOG pubs FROM DISK=N'C:\Backups\Logbackup.bak' WITH RECOVERY,
STOPAT='02/11/2002 17:35:00'

—Microsoft SQL Server 开发团队
 
--------------------------------------------------------------------------
打开UDP端口1434以浏览命名实例

更新日期: 2003年5月12日 
  
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:本地的一个ISP托管了我们的SQL Server,但是我不能看到或连接到运行在该计算机上的命名实例。我知道SQL Server 2000命名实例不使用TCP/IP 1433端口,并且确定该SQL Server实例所使用的TCP/IP端口是打开的。您有什么建议吗?

答:许多人知道如何使用SQL Server网络实用工具或SQL Server错误日志来确定SQL Server实例的监听端口。但许多人似乎忘记或者根本不知道——UDP 1434端口也必须是打开的,以确保您能够正确地访问和浏览命名实例。我建议您仔细研究一下这一要求。在SQL Server在线书籍中搜索“1434”,您将得到三个颇有研究价值的搜索结果。在SQL Server杂志网站2001年7月刊我的SQL Server实用技巧专栏中,您还可以查找到有关访问命名实例的信息(InstantDoc ID 21127)。在此我也简单解释一下。SQL Server在UDP 1434端口上建立一个监听服务,让客户端从服务器上查询到命名实例及其网络配置信息的一个列表。该监听服务始终运行在UDP 1434端口上,并且用户无法更改该运行端口。

—Brian Moran
--------------------------------------------------------------------------
如何使用系统管理员帐户管理多个开发人员?
更新日期: 2002年12月16日
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:在我们的开发环境下,每个人都有系统管理员(sa)密码,5个组使用一个数据库。在某个开发人员不小心删除了数据后,我没有办法确定谁删除哪一块数据。当开发人员更新数据库中的数据时,如何审核工作站或登录ID?

答:因为您工作于开发环境下,使用SQL事件探查器和服务器跟踪所带来的性能损失并不会影响生产环境,所以您可以设置一个服务器跟踪,在后台将信息记录在一个表中。然后,您可以搜索该表以确定谁删除了数据。

显然,一次为多个用户分配sa账户会带来许多问题。以下是您应该采取的一些措施:

为每个开发团队创建该数据库的一份拷贝,为每个团队提供一个仅数据库拥有者才有访问权的账户。这样的话,他们就不会互相影响了。
如果每个开发人员都需要sa访问权(例如运行SQL事件探查器跟踪),并且您运行的是SQL Server 2000 Enterprise或Developer Edition,您可以为每个团队提供SQL Server的一个实例及其专用的sa密码。
考虑为每个项目设置一个开发环境,并以一个集成环境的方式由一个版本数据库管理员对所有项目间冲突进行管理。这样的话,因为架构改变脚本在进入集成环境之前已经经过了测试,生产版本的质量将有所改善。
—The Microsoft SQL Server开发团队
--------------------------------------------------------------------------
防止锁定升级
更新日期: 2001年9月17日  
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:如何防止SQL Server将锁升级?

答:SQL Server使用锁来保持事务在数据库内部的完整性和一致性。SQL Server支持具有不同粒度的多种锁类型。例如,行锁是一个高级锁,而页锁是一个低级锁。SQL Server自动将大量的高级锁升级为少量的低级锁,从而降低系统开销,但同时也可能导致应用程序内不可预测的阻塞。

升级在锁的数量超过锁升级极限时自动进行。这一极限是一个内部设置,设计用于保护系统资源。该极限值不能由用户设置,但在以跟踪标记1211(无文档记载)启动SQL Server时,该锁升级将被禁用。

请注意,如果禁用了锁升级,管理系统的职责将由您承担。如果SQL Server内存不足,系统可能会崩溃。一个更好的解决方案为,如果肯定需要行级锁,可以执行较短的事务。

--SQL Server MVPs
--------------------------------------------------------------------------
 使用SQL Server导入和索引 Microsoft Word 文档 
 
更新日期: 2003年7月25日 

本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:我需要将Microsoft Word文档导入至SQL Server并索引这些文档,以便在关系查询中使用这些文档。怎样导入和索引文档呢?

答:SQL Server允许您以多种方式导入Word文档。让我们看看几种最常用的方法。请注意,在将文档导入至SQL Server之前,您需要创建一个image数据类型列,用于存放数据。然后,您可以使用textcopy.exe命令行工具将image文件读入数据库,从而完成文档的导入操作。如果需要该工具的基本说明文档,请在命令提示状态下键入textcopy /?。将Word文档导入SQL Server的另一个方法是使用Microsoft ActiveX Directory Object(ADO)Stream接口编写导入代码。您可以在Microsoft产品支持服务(PSS)的通过使用ADO Stream对象访问和修改SQL Server BLOB数据一文中找到示例代码。

此外,您也可以将二进制数据移到SQL Server中。有关这一方法的详细说明,请参阅PSS的使用ADO检索和更新SQL Server文本域一文。移动二进制数据允许您将数据的一部分存放在数据库中,这在需要控制数据格式时尤其有用。例如,如果只需要数据中1,000到1,010之间的字节,导入二进制数据的速度远远高于使用ADO Stream接口的速度,这是由于SQL Server从磁盘上检索数据的量大为减少。人们通常使用这一技术来存储位掩码,用于表示应用程序的开或关标志位。

SQL Server 2000自带了说明了如何移动二进制数据的示例代码。如需查看该代码,只需在安装有SQL Server 2000光盘上代码示例的驱动器上选择 \Program Files\Microsoft SQL Server\80\Tools\DevTools\Samples\ado路径。展开该可执行文件,在Visual Basic目录下查找Samples子目录。在Employee示例下,注意一下该代码是如何使用FillDataFields()函数的。

如需索引Word文档,SQL Server 7.0和SQL Server 2000都提供了全文搜索组件。该组件混合使用了多种技术,用以索引大型文本和image列。在执行全文搜索时,您需要指定image列所含的文件类型,以及从二进制数据中析取信息所需的筛选(filter)。有关使用全文索引的详细信息,请参阅SQL Server在线书籍中的相关主题,并阅读David Jones 2000年7月发表在SQL Server杂志网站上的名为构建更好的搜索引擎一文。请注意,索引Word文档并不会自动生成包含文档中关键字的一组关系表。但是,索引文件让您将这些Word文档包含在您的搜索中。以下是从数据中析取关键字的可行方式:

使用OLE自动处理从文档中读取用户定义的关键字。在装载该文档时将这些关键字保存在关系表中。
使用OLE自动处理打开文档并将其保存为文本(.txt)格式。为了析取重要的词语,您可以使用自己的“词语分析器”遍历该文本文件。文字分析器查看文档中的每个词语,去除一些无用文字,并将每个唯一的词语与其出现的次数一道存储起来。
在新的全文索引文档中搜索特定的关键字,并将这些关键字输入到关系表中。
SQL Server 2000提供了多个强大的工具和接口,用于帮助用户实现二进制Microsoft Office文档的快速装载、搜索和检索。

—SQL Server 开发团队
--------------------------------------------------------------------------
Ghost记录清理和602错误
更新日期: 2003年8月6日
 
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:最近,在使用SQL事件探查器监视我的SQL Server数据库时,我定期收到“Error: 602, Severity: 21, State: 13”信息。在SQL Server企业管理器的进程信息窗口中,我找到了一个名为“Ghost Record Cleanup”(幻影记录清除)的后台进程,并且该命令由用户系统所引发。我使用DBCC CHECKDB检查我的数据库,但是没有发现任何异常。请问什么是Ghost Record Cleanup进程?什么是602错误消息?

答:在从数据库中删除行、页或扩展盘区时,SQL Server会将这些对象标记为“幻影”(表示删除操作有待执行),并在稍后使用后台任务清除这些对象,该进程就是Ghost Record Cleanup。Ghost Record Cleanup改善了DELETE命令的性能,因为SQL Server无需立即执行物理清除操作。

如需了解出现602错误的原因,您可以在SQL Server错误日志中查找提供ObjectID的一行信息。然后,您可以使用该ObjectID跟踪到导致该错误的数据库或对象。如果该对象仍然存在(例如,它不是诸如临时表的临时对象),您可以对其运行DBCC CHECKTABLE,并通过查询sysindexes验证该对象并未受损。如果对象未受损,则SQL Server错误地发出了602错误消息。多数情况下,SQL Server发布了错误的消息。如需了解602错误所代表的意思,请访问Microsoft产品支持服务网站并搜索“错误消息”和602。搜索将返回一系列说明如何解决602错误及其含义的文章。

—SQL Server 开发团队
--------------------------------------------------------------------------
使用扩展属性创建数据字典工具
更新日期: 2003年3月31日
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:我正在寻找可以帮助我维护一个SQL Server数据字典的共享软件或低成本工具。我使用过具备该功能的高级数据建模工具。但是,我现在的公司有许多SQL Server数据库,但是没有数据字典,并且也没有购买价格不菲的工具的打算。您知道有哪些给“穷人”用的数据字典工具吗?

答:尽管可能有免费或低成本的共享软件工具,但我对它们不是很熟悉。我建议您尝试使用SQL Server 2000的扩展属性。在SQL Server 2000中,Microsoft添加了扩展属性,用于帮助用户在多个数据库对象上定义和操作用户定义的属性。您可以使用这些用户定义的属性向您的数据库添加元数据,并使用该数据库创建一个直接集成在SQL Server中的“土制”数据字典。

您可以使用系统存储过程sp_addextendedproperty、sp_updateextendedproperty及sp_dropextendedproperty来管理这些属性。此外,您可以使用系统函数fn_listextendedproperty()检索现有的属性值。Microsoft使用扩展属性来写入和管理描述值,它与SQL Server企业管理器表设计视图中的列相关联。

请注意,使用这些存储过程和fn_listextendedproperty()函数创建和管理扩展属性并不是一件轻而易举的事。SQL Server在线书籍中名为“属性管理”的主题提供了有关扩展属性的基本信息。幸运的是,SQL Server杂志上有几篇非常不错的相互文章。有关使用扩展属性的详细信息,请参阅Michelle A. Poolet的“一个商业元数据知识库”,William Vaughn的“管理扩展属性”,以及“技巧:管理基于SQL Server 2000扩展属性的数据字典”。这三篇文章都解释了如何使用扩展属性,并且每篇文章都提供了一个解释器,供您编写自己的“穷人”数据字典之用。

—SQL Server MVP Brian Moran
--------------------------------------------------------------------------
确保所有的非空(Non-NULL)值都是唯一的 
更新日期: 2002年6月21日  
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:我的SQL Server表的一列允许NULL值。我希望在其值为非NULL时,该列是唯一的。怎样才能以编程的方式实现这一行为?如果在该列上设置一个UNIQUE 约束,我只能包含一个值为NULL的记录。我正在使用触发器实现这一约束,您可以推荐一个更简单的方法以保证所有的非NULL值唯一吗?

答:SQL Server没有实现非NULL值唯一性的内建机制,因此您需要通过自定义的CHECK约束来实现这一机制。例如,以下一段编码实现了您所需要的功能:

USE tempdb
CREATE table t1 (c1 int NULL, c2 char(5) NULL)
CREATE trigger mytrigger on t1 for insert, update as
BEGIN
       IF (select max(cnt) from (select count(i.c1)
as cnt from t1, inserted i where t1.c1=i.c1 group
by i.c1) x) > 1
       ROLLBACK TRAN
END

在SQL Server 2000中,您还可以使用INSTEAD OF触发器来实现这一功能。有关INSTEAD OF触发器的详细信息,请参阅以下文章。如需访问这些文章,请访问SQL Server 杂志网站,在InstantDoc框中输入InstantDoc号,然后点击Go。相关文章如下:

Tricks with INSTEAD OF Triggers; InstantDoc number 15828
INSTEAD OF Triggers on Views; InstantDoc number 15791
INSTEAD OF Triggers; InstantDoc number 15524
—SQL Server MVPs
--------------------------------------------------------------------------
使用视图控制用户对数据访问 
更新日期: 2003年9月5日  
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:我的Microsoft Access 2000应用程序由后端的SQL Server 2000数据库写入数据。为防止Access的用户看到SQL Server 2000表中的全部数据,我想使用一种只允许用户浏览授权数据行的视图。可以创建一种限制用户访问SQL Server数据的视图吗?

答:可以。如果每位用户以唯一的用户ID登录到Access,您就可以创建一种限制用户访问SQL Server数据的视图。以下的示例语句就可以创建这样一种视图:

CREATE VIEW v_data AS
  SELECT <column_list>
     FROM dbo.mytable AS a
     INNER JOIN dbo.authtable AS b
     ON (a.Pkey = b.DataKey
AND b.userid = suser_sname())

该视图按userid限制用户的访问权。它要求您保存一份与数据表(mytable)中特定主键相匹配的用户名的表(authtable)。如果您的情况相对比较简单——您无需管理多个用户的行访问权,则您可以将userid列插入到数据表中,如下列代码所示:

CREATE VIEW v_data AS
  SELECT <column_list>
    FROM dbo.mytable AS a
    WHERE a.userid = suser_sname()

—Microsoft SQL Server 开发团队
--------------------------------------------------------------------------
检查端口号 
更新日期: 2003年9月5日  
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:我创建了一个使用TCP/IP网络图书馆的服务器别名。客户端服务器别名被配置为动态确定所使用的端口。怎样才能找出客户所使用的端口以便我设置自己的防火墙?

答:客户端用于联络SQL Server实例的端口与该实例用于监听客户端请求实例的端口是一样的。您有几种方法来确定正被使用的端口号。请记住,当服务器首次被安装时,SQL Server 动态地选择端口。以后每次服务器暂停工作和重新启动时使用的端口号都是一样的。动态端口分配是一次性的事件。

要查看正被SQL Server实例使用的端口号,可以选择以下的任何一种方法:

打开Server网络实用工具,点击启用的协议列表中TCP/IP条目的属性。

查看特定实例的错误日志。您会在错误日志中看到与下面相似的条目:

SQL Server listening on 127.0.0.1: 1362.
冒号后的四位数是SQL Server正用于监听IP地址的端口,冒号左边是详细的信息。

查看注册表。根据您安装和升级SQL Server的方式,具体的注册表子键会有所不同,但您会看到和下面相似的键:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
InstanceName\MSSQLServer\SuperSocketNetLib\Tcp\
InstanceName是您正在使用的SQL Server实例的名称(对于默认实例,InstanceName为MSSQLServer)。该键有一个名为TcpPort的条目,其中包含了正在被使用的端口号。
您需要这个端口号来设置客户端和服务器之间的防火墙。客户端向SQL Server的UDP 1434端口发送特殊的请求,以确定使用哪一个端口。SQL Server返回可用的服务器实例的列表,以及每个实例正在使用的端口。如果屏蔽了UDP 1434端口,则通过防火墙与SQL Server实例的连接将无法实现。
--------------------------------------------------------------------------
 
如何识别真实和自动创建的索引? 
更新日期: 2003年3月10日  
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:我发现sysindexes索引表中的很多条目并不是我自己创建的。听说它们并不是真正的索引,而是SQL Server查询优化器自动创建的统计。怎样才能识别哪些是真正的索引,哪些是SQL Server自动创建的统计呢?

答:按照默认设置,如果表中的某列没有索引,则SQL Server会自动为该列创建统计。然后,查询优化器评估该列中数据分布范围的统计信息,以选择一个更为有效的查询处理方案。分辨自动创建的统计很简单,在SQL Server 7.0和SQL Server 2000中,自动创建的统计的前缀为_WA_Sys。

您还可以使用INDEXPROPERTY()函数的IsAutoStatistics属性来区分一个索引是真正的还是自动创建的统计,让SQL Server优化器选择需要创建的统计。您还可以为您管理的数据库启用“自动创建统计表”选项。

很多人忽略了下面的明显的结论。自动创建统计的存在意味着某个真正的索引可能会从中受益。请考虑下列代码的输出:

USE tempdb
GO
IF OBJECTPROPERTY(OBJECT_ID('dbo.orders'), 'IsUserTable')=1
        DROP TABLE dbo.orders
GO
SELECT * INTO tempdb..orders FROM northwind..orders
GO
SELECT * FROM tempdb..orders WHERE orderid = 10248
GO
SELECT * FROM tempdb..sysindexes WHERE id = object_id('orders')
    AND name LIKE
'_wa_sys%'
GO


该代码在tempdb中复制Northwind Orders表,选择一行,然后检查SQL Server是否添加了一个统计。很显然,该表没有OrderId列的索引,所以SQL Server自动创建了名为_WA_Sys_OrderID_58D1301D 的统计。OrderId列统计表的存在表明Northwind Orders表将得益于附加的索引。

以下查询显示了为数据库中每个用户表自动创建的统计的数量,该数据库至少有一个自动创建的统计。

SELECT
     object_name(id) TableName
     ,count(*) NumberOfAutoStats
FROM
     sysindexes
WHERE
       OBJECTPROPERTY(id, N'IsUserTable') = 1
       AND INDEXPROPERTY ( id , name , 'IsAutoStatistics' ) = 1
GROUP BY
      object_name(id)
ORDER BY
      count(*) DESC


并不是所有的统计都可被真正的索引所替代。在某些情况下,SQL Server会为一个表自动创建超过50个统计。很明显,这些表的索引策略很差劲。对表及自动创建的与之相关联的统计的快速记数可以帮助您确定哪些表需要索引。

—Microsoft SQL Server开发团队
--------------------------------------------------------------------------
向被复制的表添加列  
更新日期: 2003年3月10日 
本技巧摘自SQL Server杂志的一期。如需了解更多的技巧,请访问SQL Server的使用技巧中心。

问:我们常常向重复的表添加列。怎样才能在不重新初始化整个发布的情况下添加一个列?

答:在SQL Server 2000中,您可以使用sp_repladdcolumn存储过程向重复的表添加列,而不需要重新初始化整个发布,因为存储过程会自动在订阅服务器上添加该列。例如,如果pubs数据库中的authors表已发布,您可以通过执行以下存储过程将newcol整数列添加到该表中:

sp_repladdcolumn @source_object = 'authors'
, @column = 'newcol'
, @typetext = 'INT'
, @publication_to_add = '<name of publication authors is included in>'

请注意,您只能使用sp_repladdcolumn存储过程向重复的表添加新列,而不能用它来管理表中现有的列。如需从已发布表中删除已有的列,您可以使用sp_repldropcolumn存储过程。

—Microsoft SQL Server开发团队

 --------------------------------------------------------------------------
将代码页从SQL Server 7.0改变到SQL Server 2000

发布日期:2002年7月1日

问:我注意到,SQL Server 7.0默认安装的代码页设置是SQL_Latin1_General_CP1_CI_AS,但是SQL Server 2000的默认代码页是Latin1_General_CI_AS。在我需要将SQL Server 7.0数据库恢复到SQL Server 2000之中时,默认代码页发生的变化会造成很大的差异。我应该如何适应这种改变?

答:SQL Server正在逐渐取消对原有的自定义代码页的支持,而转变为同Microsoft® Windows 代码页相匹配,Windows代码页是您在设置Windows区域ID时所选择设定的。同代码页相关的更多信息,请参阅SQL Server 2000在线图书中的“字符数据的存储方式”一文。

当您将SQL Server 7.0升级到SQL Server 2000之后,在默认情况下,您仍然可以保留现有的排序方式和代码页设置。但是,当您进行了一次干净的SQL Server 2000安装时,您将使用新的排序方式和代码页。如果您将某个数据库附加到一个SQL Server 2000实例中,SQL Server将保留该数据库在创建时所使用的排序规则。换句话说,如果您将一个SQL Server 7.0数据库附加到SQL Server 2000之中,你就可以保留SQL Server 7.0代码页。

由于SQL Server现在使用了新的默认代码页,我们建议:如果您想通过干净安装和数据库的附加(attch)操作进行升级,您可以在安装时选择同您的SQL Server 7.0排序规则相匹配的排序规则。您可以通过执行一次升级来确定该排序规则,例如,对pubs数据库进行一次升级,使用SERVERPROPERTY (Collation)函数运行一个查询,然后看看所得到的是何种排序规则。

Microsoft之所以对默认代码页进行修改,主要是为了减少SQL Server和Windows代码页的不兼容而引起的种种问题。

— Microsoft SQL Server开发团队

--------------------------------------------------------------------------
排序顺序会影响系统性能吗? 
 
发布日期:2002年5月8日 

问:一些资料介绍说,在SQL Server 6.5中,排序方式会对系统性能造成影响,但是我并没有发现有针对SQL Server 2000或SQL Server 7.0的类似说法。我想知道二分法检索对SQL Server 2000程序到底有何意义。SQL Server 2000所支持的各种排序方式之间在执行性能上存在哪些差异呢?

答:请记住:各类排序方式间的性能差异受制于SQL Server在数据排序和数据比较上所花费的CPU周期数量。排序速度快并不代表性能就一定会得到改善。事实上,选择较为“快速”的排序方法(例如二分法)可能会导致应用程序在其它方面的性能降低。

例如,假设您有一个查询,该查询通过last_name字段进行搜索。二分法排序的规则规定:Smith 并不等于smith。您的应用程序开发人员可以通过要求所有数菥笮葱问交蛐⌒葱问嚼词迪终飧鲆滴衤呒5牵导实慕饩霭旆ㄊ嵌运阉鞅碇械乃惺菔褂肬PPER() 或者 LOWER() 函数。但不幸的是, 如果类似UPPER()这样的函数对一个经过索引的列进行了操作,SQL Server将不再能够使用索引搜索数据。在这种情况下,通过使用二分法所获得的所有性能提升都将被花费在全表扫描上的巨大性能降低所抵消。所以,您无需考虑不同排序方法间可能存在的微小性能差异,您也无需费神考虑何种排序方法最能满足程序开发人员和最终用户的需要。

— SQL Server MVPs
--------------------------------------------------------------------------
日志文件的增长和DBCC DBREINDEX 
发布日期:2002年6月10日 

问:我有一个30GB的数据库,我使用完全恢复模式。无论什么时候,只要我使用数据库一致性检查程序(DBCC)语句DBCC DBREINDEX对特定的大型数据表进行重新索引,我都要将恢复模式改为Bulk_Logged,在重新索引过程完成后再改回完全模式。我希望这样做能够避免事务日志文件急剧增长,但是随后的日志文件备份工作量却非常大--有大约15GB。从逻辑上说,数据库中的数据在重新索引后同原先并没有什么不同,只是索引重新进行了组织,那么为什么日志文件还是那样大呢?我怎样才能避免日志文件出现这样的急剧增长呢?

答:是的,在重新索引前后的数据是完全一样的,但是索引却全面进行了更新。当您执行DBCC DBREINDEX命令的时候,SQL Server的日志仅仅记录了扩展盘区的分配情况(8页面单位),而不是记录了每一行或者每一页所发生的变化。这种类型的日志记录方式避免了物理文件由于系统故障而遭到破坏,并且将更详细的日志记录对系统吞吐量产生的影响降低到最小。

当您备份日志文件的时候,SQL Server必须对分配在扩展盘区中的页面进行备份,以便保持数据库备份和日志备份的一致性。如果SQL Server不备份这些页面,您将不能够切换回完全恢复模式,除非你进行一次完整的数据库备份。您必须能够从最近一次的完全备份、任何差异备份以及任何更新的事务日志备份中对数据库进行恢复。

— Microsoft SQL Server开发团队

--------------------------------------------------------------------------
管理结果集的分页
发布日期:2001年9月24日 
问:我怎样才能使用SQL Server对结果集的分页进行管理?

答:您经常需要使用一次一页的形式来显示一个结果集,并保证用户可以轻松查看各个结果集页面,特别是您在为Web站点开发程序的时候。虽然您可以使用ADO Recordset对象对结果集进行分页,但是这种解决办法不具有伸缩性。

为了解决伸缩性问题,您需要在结果集中包括一个具有唯一ID的列,例如在表中包括一个主键。以下代码介绍了一个简单的例子,它使用两个存储过程在各个页面间进行导航:

CREATE PROCEDURE spGetNextPage
@id varchar(11) =' 0',
@rows int = 0
AS

SET NOCOUNT ON
SET ROWCOUNT @rows

SELECT
a.au_id,
a.au_fname + ' ' + au_lname AS name
FROM
authors a
WHERE
a.au_id > @id
ORDER BY
a.au_id

SET ROWCOUNT 0
SET NOCOUNT OFF
GO

CREATE PROCEDURE spGetPrevPage
@id varchar(11) =' 0',
@rows int = 0
AS

SET NOCOUNT ON
SET ROWCOUNT @ROWS

SELECT
a.au_id,
a.au_fname + ' ' + au_lname AS name
INTO
#temp
FROM
authors a
WHERE
a.au_id <@id
ORDER BY
a.au_id desc

SET ROWCOUNT 0

SELECT
*
FROM
#temp
ORDER BY
au_id

SET ROWCOUNT 0
SET NOCOUNT OFF


本示例所使用的样本数据来自pubs数据库,您可以对authors 表进行分页。如果想返回第一页的前两行数据,您可以使用带有以下参数的spGetNextPage存储过程: EXEC spGetNextPage @id=' 0', @rows=2

spGetNextPage 过程将返回authors表的前两个作者:

172-32-1176 Johnson White Marjorie Green
如需返回接下来的两个作者,您可以将后一行的ID传递给spGetNextPage:

EXEC spGetNextPage @id='213-46-8915', @rows=2
结果页显示:

238-95-7766 Cheryl Carson Michael O'Leary
如果想移动到先前页面,您可以使用第一行的ID调用spGetPrevPage:

EXEC spGetPrevPage @id='238-95-7766', @rows=2
结果将显示了您在前面看到的第一个页面。使用这种方法的一个缺点是具有唯一ID的列决定了结果集的顺序。在本文的情况下, au_id 字段必须在作者姓名字段的前面。

— SQL Server MVPs


--------------------------------------------------------------------------
修改日志传送角色 
 
发布日期:2002年6月18日 

问:我试图创建一些能够对日志传送角色进行修改的存储过程。与主服务器相同的登录帐户已经存在于备用服务器之中。为了将这些登录帐户从主服务器上复制到备用服务器中,我是否可以只使用用来改变角色的存储过程,而不创建一个数据转换服务(Data Transformation Services,DTS)包?如果我可以只使用存储过程来完成这些工作,我是否需要执行sp_resolve_logins存储过程来解决登录帐户和数据库用户间的所有不匹配问题?

答:如果您已经将帐户复制到了备用服务器中,那么您只需使用sp_resolve_logins 过程将帐户挂接到数据库中即可,以使这些帐户同master..sysxlogin表中的安全ID(SID)相匹配。在您修改日志传送角色的时候,您必须使用sp_resolve_logins,因为SQL Server为每个用户帐户分配了一个唯一的SID,既使该用户名是先前在本台服务器或其他服务器上已经使用过的用户名也是如此。Sp_resolve_logins 可以重新设置SID,以在用户所能够访问的每个数据库中反映出新的SID。当您在多个系统中使用数据库的时候,请确信用户帐户的名称不会彼此发生冲突。

— Microsoft SQL Server开发团队

--------------------------------------------------------------------------
SQL Server 2000 Enterprise Edition的优点
发布日期:2001年9月10日

Q. 使用SQL Server 2000 Enterprise Edition(企业版)能给我带来什么好处?

A. SQL Server 2000 Enterprise Edition具有几个独一无二的特性,包括访问大于2GB的内存的能力、对故障恢复群集的支持以及分布式分区视图(aka 联合数据库服务器)。但是,就算您不需要这些特性,企业版也可以为您带来一些性能上的优化。例如,SQL Server 2000 Enterprise Edition可以根据可用的内存数量动态调整预读(read-ahead)页面的最大数量;预读页面的数量在其它任何版本的SQL Server 2000中都是固定不变的。而且只有SQL Server 2000 Enterprise Edition能让多个任务共享全表扫描。

这两个性能优化可能不会在响应时间方面带来很大的改善。但是,如果您需要最大限度地榨干应用程序的潜力,您肯定会在安装企业版时为这两个特性感到欢欣不已。您不需要手动配置它们。

更多信息

要获得同SQL Server 2000 Enterprise Edition的特性有关的更多信息,请参阅Microsoft文章“SQL Server 2000各个版本所支持的功能特性”以及“阅读文献页面”,它们都可以在MSDN站点上找到。

SQL Server 2000 Books Online (在线图书,BOL)中错误地指出:您只能在SQL Server 2000 Enterprise Edition中创建索引视图。Microsoft在文章PRB中对此进行了全面的更正:索引视图(Indexed Views)可以在所有版本的SQL Server 2000中创建,该文章可以从Microsoft 支持站点上找到。

—SQL Server MVP

--------------------------------------------------------------------------
水平分区合并复制
发布日期:2001年5月29日

Q. 在运行一个水平分区的合并复制时,为什么数据从订阅者那里消失了?

A. 数据看起来“消失”了,这个问题自SQL Server 7.0中的合并复制发布以来一直存在。合并复制使您可以在订阅数据库上处理事务并将数据传播回出版数据库。像这样的反向传播会在处理水平分区的出版时引发一个独特的问题。

在您应用水平分区时,您基本上是在查询中添加一个WHERE子句。这个WHERE子句决定了那些数据行可以被发送给一个特殊的订阅者。假定您将一个联系人数据库针对移动销售人员进行了分割,以便每个移动销售人员的数据库只保有相应于该销售人员所负责区域的联系人数据。例如,如果Joe Smith负责东部地区,他的数据库将只含有东部地区的联系人。水平分区加强了这种限制。

现在,假定Joe所负责的区域发生了变化,他现在负责东南部地区。而Joe的数据库包含的是东部地区的联系人信息,这会和水平分区规则发生冲突。在下一次合并中,Joe会收到所有东南部地区的联系人信息,以便数据库符合分区规则。但是,现在Joe既有东部地区也有东南部地区的联系人数据,这又产生了冲突。

合并复制可以防止您拥有违反分区规则的数据。因此,在合并作业将东南部地区的数据发送给Joe的时候,它还会删除Joe数据库中的东部地区的数据。这种解决办法显然会造成数据丢失,并且在分区规则改变时产生极大的网络流量。

在数据同分区规则发生冲突时,SQL Server会删除那些不符合分区规则的数据。但是,SQL Server不会限制这些数据进入到数据库中。Joe可以添加所负责地区以外的新的联系人记录。SQL Server将这些数据保存在Joe的数据库中,但是在下一次合并之后,这些数据将不会再被保留在数据库中。这样,用户好像就丢失一部分数据。但是实际上,SQL Server并没有真的删除这些数据,SQL Server将这些数据保存在出版者的数据库中,然后从订阅者的数据库中删除了所有与水平分区规则不符的数据。

在SQL Server 7.0中,如果您对订阅数据库进行了一些修改,SQL Server会简单地转储这些修改,并且覆盖它们。因此,在改变分区之前,您必需确保所有的数据都被同步了,否则您将丢失数据。SQL Server 2000包括了一个标志,该标志可以强制系统在重新整理数据以符合分区规则之前先上传所有的修改。在开始对齐数据之前,您可以通过对订阅进行重新初始化来实现数据的预对齐上传。

--------------------------------------------------------------------------
检查日期错误 
发布日期:2001年12月12日 

Q. 我正在将一个Microsoft Access程序迁移到SQL Server上,我在移动数据时遇到了一个问题。为了解决这个问题,我需要特别注意一些什么事情吗?

A. 一个常见问题是:Access支持的日期从100年1月1日起,而Microsoft Visual FoxPro支持的日期从1年1月1日起,而SQL Server的日期从1753年1月1日起。

您可能认为,程序中不可能存在早于1753年1月1日的日期,但是,在数据输入的过程中,很容易产生这个错误,日期可能在Access和Visual FoxPro中都有效,而在SQL Server中无效。您很可能会把1990年5月12日误输成199年5月12日或者190年5月12日。这可能就是您所遇到的问题的根源所在。

—SQL Server开发团队

--------------------------------------------------------------------------
使用CHECK约束来强制执行触发器的唯一值
发布日期:2002年1月21日
Q. 我的SQL Server数据表中有一列允许为空(NULL)值。在该列有非空值的时候,我想让该列的值为唯一值。通过编程实现这一目标的最佳做法是什么呢?如果我在该列中设置一个UNIQUE约束,我可以只在一个记录中保有空值。我正在使用触发器来强制执行这个限制,但是你能推荐一种更简单的方法来确保所有非空的值都是唯一的吗?

A. SQL Server没有内置的机制可以禁止非空值产生重复,所以你需要使用一个自定义的CHECK约束来实现这个限制。例如,以下代码就可以实现你所要的那种完整性。

USE tempdb
CREATE table t1 (c1 int NULL, c2 char(5) NULL)
CREATE trigger mytrigger on t1 for insert, update as
BEGIN
       IF (select max(cnt) from (select count(i.c1)
as cnt from t1, inserted i where t1.c1=i.c1 group
by i.c1) x) > 1
       ROLLBACK TRAN
END

在SQL Server 2000中,你还可以使用INSTEAD OF触发器来执行这个限制。同INSTEAD OF触发器有关的更多信息,请参阅以下文章,要查看这些文章,请访问SQL Server Magazine,在InstantDoc(快速文档)框中输入InstantDoc编号,然后点击“Go”。文章包括:

INSTEAD OF触发器的使用窍门;InstantDoc编号 15828
视图中的INSTEAD OF触发器;InstantDoc 编号 15791
INSTEAD OF触发器;InstantDoc 编号 15524

—SQL Server MVP

--------------------------------------------------------------------------
将数据库拥有者(dbo)帐户改变为系统管理员(sa) 
 
发布日期:2001年11月19日 

Q. 在我观察Enterprise Manager,或者对某个特殊的数据库运行“sp_helpdb ''”的时候,数据库的拥有者(dbo)显示为某个Microsoft Windows NT®的用户,而且该用户并没有添加到SQL Server 7.0服务器的登录当中。(该Windows NT用户是Windows NT 本地管理员组的成员。)但是,在我运行以下Transact-SQL语句时:

USE
EXEC sp_helpuser

结果显示:系统管理员(sa)帐户映射到了这个用户dbo上,对我来说,这意味着sa就是dbo。因此,执行以下语句
EXEC sp_changedbowner 'sa'

将失败,因为SQL Server认为dbo就是数据库的拥有者。究竟谁是数据库的拥有者——Windows NT用户还是sa?如果Windows NT用户是拥有者,我如何才能将dbo改变为sa?
A. sa帐户总是会被映射到dbo上,即使sa并不是数据库的真正拥有者。dbo帐户注册于master数据库的sysdatabases系统表中,这正如sp_helpdb系统存储过程显示的一样。你可以将dbo从Windows NT改变为sa。实现这一目的的最快办法是首先分离(detach)该数据库,然后以sa身份重新连接该数据库。注意,这种方法会产生停机时间。

—SQL Server开发团队

--------------------------------------------------------------------------
如何添加Oracle链接服务器 
 
发布日期:2001年11月19日 

Q. 在我试图将一个Oracle服务器作为一个链接服务器添加到安装了SQL Server的本地计算机时,操作失败了。以下是我的计算机的一些参数设置:

General
Server: \\bao\cjf (\\domain\computer name)
Product name: oracle
Data source: msdaora
Provider: proview (alias)

Security
Local login:cjf (sa)
Remote login: internal/oracle

难道SQL Server不支持将链接服务器添加到本地计算机吗?
A: 根据SQL Server Books Online(在线图书),你可以使用Microsoft OLE DB Provider for Oracle来查询Oracle数据库中的数据。SQL Server Books Online规定了该提供者工作所必须满足的几个条件。请仔细阅读这些指南以确保您满足这些条件。

例如,OLE DB Provider for Oracle需要Oracle客户端软件支持文件版本为7.3.3.4.0或更高, Oracle SQL*Net的版本为2.3.3.0.4。SQL Server在线图书包括了与如何创建一个SQL*Net别名和创建从SQL Server登录到Oracle登录有关的信息。Books Online还为如何引用Oracle数据库的实例和Oracle链接服务器中的数据表提供了一些指南。

根据这些指南,如想建立Oracle链接服务器,您应该运行以下命令:

exec sp_addlinkedserver 'localOracle', 'Oracle', 'MSDAORA', 'proview'
/* SQL Server调用服务器“localOracle”,SQL*NET将服务器引用为 proview. */

exec sp_addlinkedsrvlogin 'localOracle', false, 'sa', 'internal', 'oracle'
/* 以“sa”身份登录到SQL Server,sa将映射到Oracle中的一个内部帐户。*/

然后,以sa用户的身份登录到SQL Server服务器上,然后运行一个如下所示的分布式查询:

SELECT * FROM localOracle..Schema.Table
—SQL Server开发团队

--------------------------------------------------------------------------
SQL Server Profiler和参数化语句 
发布日期:2002年1月7日  
问:自从升级到SQL Server 2000后,我在SQL事件查看器中遇到了一个问题:我无法捕获带有参数的Transact-SQL语句。我希望获得查询执行过程中参数的实际取值,而并非诸如@p1这样的参数形式。请问如何在不引用跟踪过程中其它行的情况下对参数取值加以置换。

答:您必须获取跟踪过程的其它部分(如存储过程StmtCompleted所返回的结果),并将这些部分收集在一起(语句放在最前面)以捕获完整的查询内容。之所以会出现这样的结果,其原因在于从SQL Server关系型引擎恢复数据的SQL事件查看器方法。这样的问题在SQL Server 7.0中同样存在。然而,由于当事件产生时,位于引擎内部的参数取值是未知的,因此,我们无法在这一时刻做出修改。

--Microsoft SQL Server开发团队
--------------------------------------------------------------------------
将一个SQL Server系统用作一台PDC 
发布日期:2002年1月14日  
问:我的公司建立了一个灾难恢复站点,并且计划在一台新配备的计算机上安装SQL Server。Microsoft Windows NT管理员希望使用运行SQL Server的计算机作为主域控制器(PDC)。我听说,由于PDC需要完整维护与复制网络帐号数据库所引发的资源密集型任务并且需要执行网络登陆验证操作,因此,这种配置方案并非一种良好的方式。那么,请问运行SQL Server的计算机能够转而充当备份域控制器(BDC)呢?从技术上讲,将SQL Server配置为PDC或BDC是否可能呢?

答:当您在PDC或BDC上安装SQL Server时,它仍可保持良好的工作状态。如需确定某种配置方案能否适应于您的站点,应当考虑您所拥有的资源。如果您拥有足够的网络带宽、内存空间与空闲处理器,那么,使用运行SQL Server的计算机作为域控制器便是一种合理的方案。然而,在这种情况下,根据域的实际规模,相应的计算机可能需要承担大量工作负载。如果您认为SQL Server的任务将会非常繁重,那么,便请不要再让其运行任何其它服务。

--Microsoft SQL Server开发团队
--------------------------------------------------------------------------
管理技巧 
发布日期:2002年1月28日
问:我尝试将数据库备份到网络共享资源上的一个文件中,并将其恢复到另一台服务器上。我试图通过下列语句借助net use命令在目标服务器上创建共享资源:

NET USE * \\PS5\C /USER:ONEDEV\domain id
password /PERSISTENT:NO
然而,系统却始终返回消息“无法获得尚未分配的可用驱动器盘符”。此时,SQL Server企业管理器明明显示出许多可用驱动器。请问我应如何解决这一问题?

答:您只需直接使用统一命名约定(UNC)路径来备份您的数据库。SQL Server并非按照与用户相同的方式来看待映射驱动器盘符。您需要在您的共享资源\\PS5\C上为SQL Server服务帐号授予完整的访问权限,创建一个新的共享资源,或使SQL Server服务帐号成为名为PS5的计算机上的管理员组成员。

--Microsoft SQL Server开发团队
--------------------------------------------------------------------------
将事务日志移动到不同的驱动器 
发布日期:2002年1月2日  
问:如何将数据库事务日志移动到不同的驱动器上?
答:您可以通过用于分离与附加数据库的SQL Server存储过程来移动事务日志。您需要对数据库进行分离,移动日志文件,然后再将其重新附加到数据库上。举例来说,如果要将pubs数据库从C驱动器移动到D驱动器,应首先使用以下格式的sp_detach_db命令分离数据库:

EXEC sp_detach_db 'pubs'

接下来,将pubs.mdf与pubs_log.ldf文件拷贝到目标驱动器上。以下示例显示了如何将这两个文件拷贝到d:\mssql7\data目录下:

copy c:\mssql7\data\pubs.mdf d:\mssql7\datacopy c:\mssql7\data\pubs_log.ldf d:\mssql7\data

最后,当您完成文件拷贝操作后,便可使用sp_ attach_db存储过程将数据重新附件到SQL Server上:

EXEC sp_attach_db 'pubs', 'd:\mssql7\data\pubs.mdf', 'd:\mssql7\data\pubs_log.ldf'

--SQL Server开发团队
--------------------------------------------------------------------------
避免Autoclose和Autoshrink选项
发布日期:2001年12月18日

问题:我在Microsoft SQL Server 2000资源工具包中读到了一个用于就应当避免使用的选项对所有数据库进行检查的存储过程。我能够理解为何应当避免使用诸如脱机、仅供DBO使用、关闭统计信息、从检查点截断日志信息这样的选项。然而,其中所包含的两个选项——autoclose和autoshrink——则令我迷惑不解。

Autoclose。 当不再需要使用时自动关闭文件似乎是一种非常明智的做法。然而,即使当我仅在企业管理器中查看数据库时,也总是能够在SQL Server的错误日志中看到有关文件打开与关闭操作的出错信息。请问在企业管理器中浏览数据库列表是否会导致某些文件被打开呢?对于那些只在导入分段区域时偶尔使用以及只在使用在线事务处理(OLTP)数据库时进行访问的数据库来说,我认为设置autoclose选项是很有意义的。SQL Server在线图书中指出,在SQL Server个人版中,autoclose选项将自动设置为YES(开启状态),而对于其它版本,该选项将被设置为NO(关闭状态)。这个选项是否真的只适用于SQL Server个人版呢?

Autoshrink。Autoshrink选项看起来同样是非常有益的。然而,在导入分段区域的过程中,由于需要在很短时间内产生大量数据,为了确保这些区域占用最小空间以便进行备份,是否应当使用autoshrink选项呢?

解答:Autoclose在SQL Server 2000的所有版本中均可使用。尽管通过使用这一选项所节省的内存空间相当有限,但是,这些空间对于在只有有限内存资源的系统上运行的SQL Server个人版来说,仍是非常重要的。然而,在其它版本的SQL Server中启用autoclose选项并非一种明智之举,这是因为,当您每次试图访问数据库时,相应的查询操作将因数据库的装载过程而变慢。至于您所提到的文件打开与关闭问题,正如您所说的那样,当您在企业管理器中列举数据库时,实际已对数据库进行了访问,因而会打开相应的文件。

在产品化系统中将autoshrink选项设置为开启状态同样并非明智之举(除非您真的需要这样做),这是因为,当您的系统正在忙于完成其它任务时,autoshrink选项可能会同时启动,从而降低系统运行速度。然而,对于那些数据库管理员无暇估计并且数据库尺寸有可能在您毫无察觉的情况下超出控制范围的桌面或远程系统来说,开启这一选项却是一种非常有效的措施。

—SQL Server开发团队
--------------------------------------------------------------------------
SQL Server 2000 Enterprise Edition的优点  
发布日期:2001年9月10日 

Q. 使用SQL Server 2000 Enterprise Edition(企业版)能给我带来什么好处?

A. SQL Server 2000 Enterprise Edition具有几个独一无二的特性,包括访问大于2GB的内存的能力、对故障恢复群集的支持以及分布式分区视图(aka 联合数据库服务器)。但是,就算您不需要这些特性,企业版也可以为您带来一些性能上的优化。例如,SQL Server 2000 Enterprise Edition可以根据可用的内存数量动态调整预读(read-ahead)页面的最大数量;预读页面的数量在其它任何版本的SQL Server 2000中都是固定不变的。而且只有SQL Server 2000 Enterprise Edition能让多个任务共享全表扫描。

这两个性能优化可能不会在响应时间方面带来很大的改善。但是,如果您需要最大限度地榨干应用程序的潜力,您肯定会在安装企业版时为这两个特性感到欢欣不已。您不需要手动配置它们。

更多信息

要获得同SQL Server 2000 Enterprise Edition的特性有关的更多信息,请参阅Microsoft文章“SQL Server 2000各个版本所支持的功能特性”以及“阅读文献页面”,它们都可以在MSDN站点上找到。

SQL Server 2000 Books Online (在线图书,BOL)中错误地指出:您只能在SQL Server 2000 Enterprise Edition中创建索引视图。Microsoft在文章PRB中对此进行了全面的更正:索引视图(Indexed Views)可以在所有版本的SQL Server 2000中创建,该文章可以从Microsoft 支持站点上找到。

—SQL Server MVP
--------------------------------------------------------------------------
区分大小写比较
2001年8月6日 

问:如何在不区分大小写的 SQL Server 7.0 实例上编写能够对用户输入密码进行大小写比较的程序?

答: 如果已经将系统升级为 SQL Server 2000,则可以在列级别指定数据排序规则。(SQL Server 2000 Books Online 词汇表将排序规则定义为“一组确定如何比较、排列和呈现数据的规则。字符数据是使用排序规则存储的,这些规则包括区域设置、排序标准和区分大小写”。)

但是,只有升级到 SQL Server 2000,您才可以使用下列技术。假设存储在表中的密码值为 BamBi2000(注意“B”是大写,其他所有字符都是小写):

DECLARE @user_password varchar(12)

IF CAST (@user_password AS varbinary(12)) =
CAST ('BamBi2000' AS varbinary(12))
PRINT 'Password match'
ELSE
PRINT 'Password mismatch'

-SQL Server MVPs
--------------------------------------------------------------------------
收集SQL Server统计信息

问:我需要在运行SQL Server的机器上定期收集诸如每秒处理事务数(tps)之类的统计信息。为此,我大量使用了Performance Monitor(性能监视器),但却不能得到DBA所需的SQL Server性能指标。请问是否存在能够轻松收集这类统计信息的实用工具?

答:针对SQL Server的Performance Monitor计数器之一便能收集tps,因此,使用Performance Monitor是捕获这项指标最便捷的方式。您可以通过Microsoft Windows® NT Server 4.0 Resource Kit或Microsoft Windows 2000 Server Resource Kit以服务的形式安装Performance Monitor。此外,我建议您阅读Steve Adrien DeLuca等人所著的《Microsoft SQL Server 7.0 Performance Tuning Technical Reference》以学习关于测试有用SQL Server性能数据的内容。
——Microsoft项目经理,Richard Waymire

欲获取更多相关信息
正如Windows 2000 Magazine创始人所说,SQL Server Magazine为数据库管理员及开发人员提供了将SQL Server作为一种开发平台所需的各种信息与技术。请马上访问SQL Server Magazine以获取其它关于SQL Server的技巧与技术信息。

订阅SQL Server Magazine,您将获得一份来自Microsoft的免费礼品。

访问SQL Server Support Quick Tips以获取更多与SQL Server相关的现成技巧。
--------------------------------------------------------------------------
为SQL Server 配置一个邮件配置文件
2001年6月18日

问:关于为SQL Server 2000 和 SQL Server 7.0 配置一个邮件配置文件,我需要了解些什么?

答:您可以配置一个SQL Server邮件配置文件以便于通过运行Transact-SQL 代码来发送和接受邮件(例如:使用xp sendmail 扩展存储过程来发送e-mail)。您还可以为SQL Server Agent配置一个邮件配置文件,以便于在特定的作业失败或产生一个报警的时候,会自动给操作员发送一封e-mial。用邮件配置文件可以确定邮件服务器以及服务器是POP3服务器还是SMTP服务器、SQL Server登录名和密码这样的连接细节。为SQL Server和SQL Server Agent服务配置邮件配置文件的过程和为您的邮箱配置邮件配置文件以使您可以从邮件客户端收发邮件的过程基本上相同。但是您需要考虑以下的几个问题,这些问题是单指配置SQL Server而言,不是指配置SQL Server 和 SQL Server Agent。

为了使用邮件服务,SQL Server 帐户必须在一个正确的Microsoft Windows NT®帐户下启动,并且不能是一个本地系统帐户。因为SQL Server和SQL Server Agent 服务必须能够访问邮件服务器,该帐户需要对网络进行访问。但本地系统帐户不能对网络进行访问。

使用运行SQL Server 服务所需要的Windows NT 域和帐户登录到运行SQL Server的计算机上,然后可以创建邮件配置文件。注意:邮件配置文件和“我的文档”文件夹一样与特定的登录帐户有关。例如:如果您在您自己的帐户(比如:DOMAIN\SmithJ )下创建了一个邮件配置文件,但是SQL Server运行在它自己的帐户(DOMAIN\SQLServer)下,那么SQL Server不能够检测到或者不能够使用这个邮件配置文件。

在开始创建您的邮件配置文件之前,请确信SQL Server 可以连接到邮件服务器。简单地用“Ping”命令测试一下就可以了。
--------------------------------------------------------------------------
自动增长是否会阻塞更新?
2001年6月25日 

问:在数据文件自动增长时,自动增长是否会阻塞对文件的更新?

答: 不会,但是因为 SQL Server 阻塞了对分配页的更改,而分配页跟踪自动增长过程中所使用的文件部分,所以数据文件的自动增长阻塞了新扩展部分的分配。这些分配页是全局分配映射 (GAM) 和辅助 GAM (SGAM)。(请参阅 SQL Server Books Online-BOL 可以获得有关 GAM 和 SGAM 的详细信息。)因此,自动增长操作阻塞了扩展过程,因此其他操作无法使用扩展部分。例如,这种阻塞会影响需要分配新空间的 INSERT 和 UPDATE 操作。例如 INSERT 和 UPDATE 这样的操作必须等待自动增长操作完成后才能进行。自动增长不应该影响要收回现有未用空间的 INSERT 操作,和使用原有空间执行的 UPDATE 操作,以及将在页中留下自由空间的 DELETE 操作。因为检索数据不会涉及任何新的空间分配,所以自动增长操作不会影响 SELECT 操作。
--------------------------------------------------------------------------
水平分区的合并发布
2001年5月29日
问:为什么当进行水平分区合并发布的时候,订阅服务器上的数据消失了?

答:自SQL Server7.0中发布了合并复制以来,数据好像“消失”了一直是一个问题。合并复制使您能在订阅服务器上进行事务处理并且将数据传回发行服务器数据库。这样的反向传播数据在您进行水平分区的数据发布时,会出现独特的问题。

在使用水平分区的时候,您主要是在查询语句中加了一个“WHRER”子句。“WHERE”子句决定了表中的哪些行会被发送给特定的订阅服务器。假定您对联系人数据库进行了分割,使得每个销售人员的数据库只对应于他们各自负责的区域。例如:如果 Joe Smith 负责东部区域,他的数据库将只包含东部区域的联系人数据。水平分区加强了这种限制。

现在,假定销售人员的负责区域改变了。Joe 现在负责东南区域。但Joe的数据库现在包含的是东部区域联系人的数据,这会和水平分区规则发生冲突。在下一次合并复制时,Joe会收到东南区域联系人的数据以遵守分区规则。然而,现在Joe的数据既包括了东部区域的数据页包括了东南区域的数据,这又和分区规则产生了冲突。

合并复制会防止数据和分区规则发生冲突。因此,当合并作业把东南区域的数据发送给Joe时,它会从Joe的数据库中删除东部区域的数据。这种做法会造成表面上的数据丢失,并且不论什么时候改变了分区规则,解决冲突的过程都会造成网络流量的大量增加。

当有数据和分区规则发生冲突时,SQL Server 删除这些发生冲突的数据以遵守分区规则。但是,SQL Server 对进入数据库的数据不做限制。Joe可以添加负责区域以外的新联系人的信息。SQL Server会把这些数据保存在Joe的数据库中,但是在下一次合并复制后,数据不会仍然被保留在Joe的数据库中。因此,用户会发现数据库中的数据丢失了,但是实际上SQL Server并未将数据丢失。SQL Server只是把数据存储在发行服务器的数据库中,并且从订阅服务器中删除了与水平分区规则不符的所有数据。

在SQL Server 7.0中,如果您在订阅服务器上做了一些修改,SQL Server会简单地丢弃这些变化并覆盖它们。因此,在改变分区规则之前,您必须确保对所有数据都进行了同步,否则您将会丢失数据。SQL Server 2000中包含了一个标志,在重新组合数据以遵守分区规则之前,该标志强迫将所有变化上传。在重新组合数据之前,您可以把订阅标记为“自动初始化(reinitialization)”来完成预组合上传。
--------------------------------------------------------------------------
为数据库对象授予权限
2001年7月30日 

问:为什么在使用动态 SQL 语句时必须为低层数据库对象授予权限?

答: 出于安全原因需要这些权限。请考虑下列简单存储过程:

USE pubs
GO

CREATE PROCEDURE GeneralSelect @TableName SYSNAME
AS
EXEC ('SELECT * FROM ' + @TableName)
GO

您可能希望您的存储过程发出一个与下面类似的调用:

USE pubs
EXEC GeneralSelect 'authors'

但是,请考虑传送给存储过程的下列顺序:

USE pubs
EXEC GeneralSelect 'authors DROP TABLE authors'

如果存储过程的创建者是 pubs 数据库中 db_owner 角色的成员,并且您的用户只需要对存储过程具有 EXECUTE ㄏ蓿蚋妹罱境?authors 表。SQL Server 通过要求用户证明具有对数据库对象(通过动态 SQL 语句引用的)的正确权限来保护数据免受未授权的操作。

-SQL Server MVP
--------------------------------------------------------------------------
SQL Server 窍门
2001年5月3日
我被关在SQL Server 外面了。我怎样才能进去?

问:我把我自己关在SQL Server 外面了,不能作为“sysadmin”登录。有什么办法解决吗?我需要重新安装SQL Server吗?

答:您不必重新安装SQL Server。要想重新访问SQL Server,您需要修改SQL Server 2000 和 SQL Server 7.0决定SQL Server身份验证模式的注册表键值。

在SQL Server 7.0中,该键为:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft \MSSQLServer\MSSQLServer\LoginMode
在SQL Server 2000中,该键为:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
MicrosoftSQLServer\\MSSQLServer\LoginMode
“LoginMode”的值为0表示只进行Windows 的身份验证,为1表示验证模式为混合模式。在您把自己关在外面之后,您可以把“LoginMode”改为1,重新启动SQL Server,然后以sa(system administrator)身份登录,输入您知道的sa密码即可。

以下关于SQL Server的角色成员的信息可能会帮助您理解为什么您会把自己关在SQLServer外面。在您安装SQL Server 2000 或 7.0的时候,安装进程自动地为“BUILTIN\Administrators”创建一个登录帐号,该帐号为“sysadmin”角色成员。“BUILTIN\Administrators”登录帐号代表了Microsoft Windows® 2000 或Microsoft Windows NT® server 上的系统管理员本地组。 Windows 2000 或 Windows NT的 “Administrator”帐户是系统管理员本地组的成员。此外,如果您的服务器是一个域的成员(包括Windows 2000 的域和Windows NT 4.0的域),“Domain Admins”全局组也会成为本地系统管理员组的成员。这意味着系统管理员本地组的所有成员都会自动地获得SQL Server上的“sysadmin”权限。

为了加强您的SQL Server的安全性,您可能更愿意创建您自己的组并授予它“sysadmin”权限,然后删除“BUILTIN\Administrators”登录帐号,或者至少从“sysadmin”服务器角色中删除它。使用这种方法,您可以较好地对谁可以访问您的SQL Server进行控制。这种方法也断开了SQL Server 系统管理员和Windows 2000 或 Windows NT 管理员之间的联系, 因为他们通常有不同的任务,并且需要不同的权限。为了加强安全性,您可能想把SQL Server配置成只支持Windows身份验证。但是,必须要记住:这种配置会禁用您的“sa”帐户。(这个方法可能是禁用“sa”帐户的唯一方法,因为您不能删除“sa”帐户。)如果您以错误的顺序实施了这个安全措施,您将不能再以>“sysadmin”的身份登录到SQL Server上,除非按照我上面所说的方法修改注册表键值。正确的顺序是:

创建Windows 2000 或者 Windows NT 用户组并为组分配成员。例如:创建一个叫做“SQLAdmins”的组。
把“SQLAdmins”映射为SQL Server里的一个用Windows身份验证方式验证登录的帐户,并把该帐户分派到“sysadmin”服务器角色。
删除“BUILTIN\Administrators”登录帐户或者把它从“sysadmin”服务器角色中删除。
把SQL Server的身份验证模式改为“仅进行Windows身份验证”。
重新启动SQL Server 以反映身份验证模式的变化。
注意: 如果您以下面的这种错误顺序实施这些步骤:删除“BUILTIN\Administrators”登录帐户,改变SQL Server 的身份验证模式为“仅进行Windows身份验证”,然后重新启动SQL Server,那么“sa” 帐户将被禁用,并且因为没有定义其它Windows身份验证登录帐户而无法进入SQL Server。为了避免这种情况发生,请以正确的顺序实施这些安全措施。

--------------------------------------------------------------------------
在发生故障的节点上重新安装 SQL Server
2001年7月9日 

问: SQL Server 2000 Enterprise Edition 将在两个群集服务器上同步安装 SQL Server 可执行文件和程序文件。如果其中一台服务器发生故障,应该如何重新构建服务器并在该节点上重新安装 SQL?

答: 可以在 SQL Server Books Online 中查找 SQL Server 2000 群集过程。运行安装程序,从配置中删除失败节点,修复节点,然后重新运行安装程序。在将该节点添加回 SQL Server 2000 配置时,SQL Server 将对自身进行适当地重新安装并重新配置。

-Richard Waymire, Microsoft Group Program Manager for SQL Server Management Tools
--------------------------------------------------------------------------
在第二台计算机上运行DTS作业 
Q. 我的顾问可以设置和运行基本的SQL Server 7.0数据转换服务(Data Transformation Services,DTS)作业。但是他们声称,只能在创建作业的计算机上运行它们。他们告诉我,如果在不同的计算机上运行这个作业,所有保存的设置不得不重新设置和重新保存。这种返工对我没有意义(但是我不是一个 SQL Server数据库管理员)。尽管如此,在读完了关于DTS的几个问题与解答(Q&A)后,我怀疑这个问题可能与权限有关。你们能否提供一些指导?
A. 你的顾问不完全正确。要在另一个系统中运行作业,你确实需要改变用户ID。因此如果你使用一组用户ID开发连接对象,可能需要在部署这个软件包时需要改变这些ID。

但是,要进行这些修改,你不需要直接编辑DTS包。Darren Green的网站中有关于如何在 SQL Server 7.0中改变用户ID的例子。在SQL Server 2000中,你可以使用UDL(Universal Data Link,通用数据链接)或新的DTS动态属性(Dynamic Properties)任务,在运行过程中改变连接。要了解有关DTS的更多信息,请参阅SQL Server DTS新闻组。你还可以通过在SQL Server Magazine网站上浏览公共论坛和搜索关键字“DTS”,找到关于DTS的信息。
 
--------------------------------------------------------------------------
SQLAgentCMDExec 权限
2001年5月14日

问: 我想在SQL Server 7.0 Enterprise Manager上用SQLAgentCMDExec 帐户创建一个作业,以使Visual Basic 6.0 可执行程序能被计划执行。.exe程序使用UNC(universal naming convention)路径在运行SQL Server 7.0的计算机的共享目录上创建一个文件。 结果当我在服务器上运行或在命令提示符下运行时,.exe 程序运行正常。但是,当我在Enterprise Manager上运行时,它不能正常工作。作业的帐户拥有者对我想创建文件的文件夹具有“完全访问”权限。我怎样才能让程序在Enterprise Manager上工作呢?

答:作业的安全要根据作业拥有者的访问权限。如果作业拥有者是SQL Server系统管理员,SQL Server运行于的服务帐户可以运行.exe文件。如果作业拥有者不是一个系统管理员,SQL Server使用SQLAgentCMDExec帐户作为安全环境来运行作业。因此, SQLAgentCMDExec 帐户需要权限来执行您的可执行程序所执行的同样任务。使用您所指定的作业拥有者,作业不会运行,因为SQL Server不支持用户不使用Windows NT密码对SQLServerAgent 服务进行登录。

--------------------------------------------------------------------------
在建立索引时访问数据表
2001年6月11日

问:当我正在为表建立索引的时候,SQL Server 会禁止对表的访问吗?

答:在您建立索引时,SQL Server 不会禁止您对表进行读访问,除非您正在建立一个簇索引。然而,如果某人此时试图更新表中的数据,SQL Server 会禁止更新操作 - 不管您正在创建什么样的索引类型 - 因为您不能取得表级别的独占锁(IX lock)。独占锁会和CREATE INDEX 语句持有的共享锁发生冲突。

当SQL Server 完成了建立索引的操作后,它必须修改系统表来反映数据表的变化;两个最主要被修改的系统表是sysindexes 和 sysobjects 表。因为您没有使用“normal”SQL来建立索引,所以您不能对SQL Server的操作进行跟踪。

在最后一个阶段, 独占锁(IX lock)并不出现在数据表中,而是出现在系统表正在建立索引的相应数据表项上。 一般来说,最后这个阶段比较短,因为SQL Server已经对数据进行了排序并抽取了行指针(物理行定位符或簇索引键)。唯一剩下的任务就是修改系统表,这个过程很快。如果系统表上的独占锁还在,您不能执行任何查询操作,因为您不能从sysindexes 和 sysobjects系统表中读取出所需要的信息。
--------------------------------------------------------------------------

posted on 2005-09-11 14:08 回头重来 阅读(...) 评论(...) 编辑 收藏