SQL Server技巧合集2005-04-2

SQL SERVER中对查询结果随机排序
问:怎样才能对查询结果随机排序?
  答:对结果记录随机排序,或随机返回X条记录,可以通过在SELECT语句中使用RAND函数来实现。但是RAND函数在查询中只生成一次,因此每一行都将得到相同的值。可以通过在ORDER BY子句中使用NEWID函数来对结果进行排序的方法来实现,代码如下:
  SELECT *
  FROM Northwind..Orders
  ORDER BY NEWID()
  SELECT TOP 10 *
  FROM Northwind..Orders
  ORDER BY NEWID()
解决SQL Server 2000之日志传送功能
一、残余数据
     当您进行SQL Server 2000日志传送的实验时,也许偶而会中断设定过程。如果真是如此,那么某些资料仍然会存入每台服务器的日志传送资料表,并且影响到后续的日志传送设定动作。为了保证这些剩余资料都会被清除,请确实删除每台服务器msdb数据库内日志传送资料表之相关资料。
    错误信息:
    Error 14261: The specified primary_server_name.primary_database_name ('N') already exists.
    Error 14426: A log shipping monitor is already defined (...)
    处理方法:
    必须手动执行下面几个存储过程来删除Log Shipping在数据库中记录的信息。
    1、sp_delete_log_shipping_primary
     删除msdb.dbo.log_shipping_primary表中的Primary Server信息
    2、sp_delete_log_shipping_plan
     删除Log Shipping计划
    3、sp_delete_log_shipping_secondary
     删除msdb.dbo.log_shipping_secondaries表中的Secondary Server信息
    4、sp_remove_log_shipping_monitor
     删除Log Shipping监视从表msdb.dbo.log_shipping_monitor
二、数据库的模式
     如果正确设置了Log Shipping,但是没有办法正常执行,在SQL Server的日志中可以看到类似这个信息和界面:
    Microsoft (R) SQLMaint Utility (Unicode), Version Logged on to SQL Server 'ZTAO-1' as 'ZTAO-1/Administrator' (trusted)
Starting maintenance plan 'LOG_Plan_9' on 2003-9-4 14:42:02
Backup can not be performed on database 'ERPLogShipping'. This sub task is ignored.
Deleting old text reports...        0 file(s) deleted.
End of maintenance plan 'LOG_Plan_9' on 2003-9-4 14:42:02
SQLMAINT.EXE Process Exit Code: 1 (Failed)

    可能是你没有正确设置数据库的模式,完整模式。

    三、Log文件存放路径
    在MSDN上看过一篇文章说,同一台电脑上再次设置Log Shipping时,不要使用相同的目录存放Log文件。这个没有考证过,只提一下,提醒大家!
数据库考试简介——微软数据库管理员 (MCDBA)
微软认证数据库管理员 (MCDBA) 可获得如下权益(2000 年 1 月 1 日生效):
  业界对您具备的微软产品和技术的知识与熟练程度的认可。
  在取得认证的第一年内订阅全年 TechNet 或 TechNet Plus 享有预零售价的 50% 的折扣。(实行细节可能会随着您的所在地点有所变化,请查看您的 Welcome Kit。)
  订阅“微软开发人员网络”(MSDN?)在获得认证后的一年内,MCDBA 可以获得一年的 MSDN 订阅折扣.(实行细节可能会随着您的所在地点有所变化,请查看您的 Welcome Kit。)MSDN 专业版的折扣额为 200 美元,MSDN Universal(通用版)的折扣为 500 美元。
  订阅一年期 SQL Server Magazine。 SQL Server Magazine 是供 SQL Server 专家阅读的首选资源。该杂志由业界的专家撰稿,包含了技术和实际技巧以及有关建议,是每位使用 SQL Server 人士的必备之物。通常全年的定价是 49.95 美元,对于 MCDBA 免费。
  通过 安全的 MCP Web 站点 直接从微软公司获得技术和产品信息。
  从部分公司获得独享的产品和服务折扣。现已通过认证的个人可以通过访问 MCP 安全站点 ,并单击“其他权益”来获取有关的独享折扣信息。获得最高级认证的人员可以选择“最高级权益”。
  MCDBA 徽标、证书、成绩单、皮夹卡、领带夹向同事和客户表明您的微软认证专家(MCP)身份。在认证时可以从 MCP 安全 Web 站点 下载徽标和成绩单的电子文件。
  邀请参加微软举行的会议、技术培训会议以及特别活动。
  免费访问 Microsoft Certified Professional Magazine Online (《微软认证专家在线杂志》 -- 一份有关职业生涯及专业前景展望的杂志)。 Microsoft Certified Professional Magazine Online Web 站点的安全内容包括本期杂志(只有 MCP 才能访问),其他仅在线发行的内容和专栏,一个只对 MCP 开放的数据库和与微软和其他技术专家定期的在线技术讨论。
  加入 PASS(SQL Server 专业协会)时享有折扣。除了在其中扮演重要角色外(这是唯一由用户主持并经过 Microsoft 批准的全球性 SQL Server 用户组),该协会的成员还能够独享各种教育机会。PASS 还邀请 MCP 利用 PASS 的表决资格,只需 50 美元即可享受会员的所有权益(比正常价格低 100 美元)。 请访问 MCP 安全 Web 站点 了解有关如何获得此项权益的详细信息。
  MCDBA 要求
  微软认证数据库管理员 (MCDBA) 报考人需要通过三门核心考试和一门选修考试,这些考试能够有效和可靠地衡量实施和管理 Microsoft SQL Server数据库的技术熟练和精通程度。

 Microsoft 正在将 Microsoft Windows? XP 专业版和 Microsoft Windows? .NET Server 考试整合到 MCDBA 认证中。应继续参与 Windows 2000 的培训和认证,因为获得的 Windows 2000 技能与 Windows XP 专业版和 Windows .NET Server 密切相关,并为后两者提供重要的基础。Windows 2000 系列的 MCDBA 不需要通过 Windows XP 专业版/Windows .NET Server 考试,即可继续持有 MCDBA 认证。MCDBA 认证的 Windows 2000 考试和 Windows XP/Windows .NET Server 考试预计将继续同时提供。
  选择下面的考试,获得有关考试目标和准备资源的信息。针对 Windows XP/Windows .NET Server 的所有考试目前尚未推出。此外,这里提供了指向对应资源的链接,这些资源可以帮助进行考试准备。

核心考试 - MCDBA 参考人需要通过一门 SQL Server 管理考试和一门 SQL Server 设计考试。此外,MCDBA 参考人还可以选择通过一门 Windows 2000 或一门 Windows .NET Server 考试,以满足核心要求。
SQL Server 考试
Exam 70-028 -Administering Microsoft SQL Server?7.0

Exam 70-228 -Installing, Configuring, and Administering Microsoft SQL Server? 2000 Enterprise Edition
Exam 70-029 -Designing and Implementing Databases with Microsoft SQL Server 7.0

Exam 70-229 -Designing and Implementing Databases with Microsoft SQL Server 2000 Enterprise Edition
Windows 2000 考试
Exam 70-215 -Installing, Configuring, and Administering Microsoft Windows 2000 Server
Windows XP/Windows .NET Server 考试
Exam 70-275-Installing, Configuring and Administering Microsoft Windows?.NET Server (2002 年推出)


Exam 70-215 的替代考试 - 通过了 Windows NT 4.0 Exam 70-067 和 70-068 的参考人可以选择参加如下考试,代替上面的 Windows 2000 系列中的 Exam 70-215。
Exam 70-240* -Microsoft Windows 2000 Accelerated Exam for MCPs Certified on Microsoft Windows NT? 4.0.(在 2001 年 12 月 31 日之前提供。有关详细信息,请参阅 常见问题解答 。)


选修考试(只需要考一门,从下面的列表中选择)
Exam 70-015 -Designing and Implementing Distributed Applications with Microsoft Visual C++ 6.0
Exam 70-019 -Designing and Implementing Data Warehouses with Microsoft SQL Server 7.0
Exam 70-155 -Designing and Implementing Distributed Applications with Microsoft Visual FoxPro? 6.0
Exam 70-175 -Designing and Implementing Distributed Applications with Microsoft Visual Basic? 6.0
Exam 70-216 -Implementing and Administering a Microsoft Windows 2000 Network Infrastructure
Exam 70-276-Implementing and Administering a Microsoft Windows .NET Server Network Infrastructure (2002 年推出)


Exam 70-216 的替代考试 - 通过了 Windows NT 4.0 Exam 70-067 和 70-068 的参考人可以选择参加如下考试,代替上面的 Windows 2000 系列中的 Exam 70-216。
Exam 70-240* -Microsoft Windows 2000 Accelerated Exam for MCPs Certified on Microsoft Windows NT? 4.0。(在 2001 年 12 月 31 日之前提供。有关详细信息,请参阅 常见问题解答 。)

* 通过 Exam 70-240 的人员可将该考试的学分作为 MCDBA 系列中的核心考试和可选考试的学分。一般来说,在认证中,可用作核心考试或者可选考试计算学分的考试只能计算一次。MCDBA 系列中的考试 Exam 70-240 是个例外。
SQL mail正确配置和使用
SQL mail主要是要完成这样的功能有:

用户在网上注册后,系统将随机产生的密码发送到用户登记的Email

用户在论坛的帖子有回复时将内容发送到用户的Email

因为上述过程都是在存储过程中完成的,所以避免了前台程序对参数的传输处理,也不需要再用第三方的组件完成,感觉比较方便。 

1.为了使用SQL mail,首先你的服务器上得有SMTP服务,我没有安装win2000 server自带的SMTP,而是用imail6.04的SMTP,感觉比较稳定,功能也比较强。

2.安装一个邮件系统,我安装了outLook 2000,我发现在配置邮件profile时,如果不安装outLook而是用别的第三方程序,win2k中文server版在控制面板中就找不到“邮件”一项。

3.安装完outlook后再刷新控制面板,就会找到“邮件”一项,双击进行邮件的配置,为配置文件起一个名字(假设为myProfile),以便以后SQL mail使用,在该配置文件中设置各项属性。

4.启动outlook(设置为用myProfile作为默认的配置文件),测试进行收发邮件,确认outlook工作正常。

5.用当前的域账户启动SQL server,在企业管理器的支持服务中,点击SQL mail的属性,可以看到在配置文件选择中,出现了刚才定义的myProfile配置文件(你也可以定义多个profile),选择这个配置文件进行测试,SQL将返回成功开始和结束一个MAPI会话的信息,如果出现错误或是没有找到邮件配置文件,那一定是你启动SQL server用的账号有问题。

6.现在你就可以在查询分析器中用XP_sendmail这个扩展存储过程发送SQL mail了,格式如下:

xp_sendmail {[@recipients =] 'recipients [;...n]'} 
        [,][@message =] 'message'] 
        [,][@query =] 'query'] 
        [,][@attachments =] attachments] 
        [,][@copy_recipients =] 'copy_recipients [;...n]'
        [,][@blind_copy_recipients =] 'blind_copy_recipients [;...n]'
        [,][@subject =] 'subject']
        [,[@type =] 'type'] 
        [,][@attach_results =] 'attach_value']
        [,][@no_output =] 'output_value'] 
        [,][@no_header =] 'header_value'] 
        [,][@width =] width] 
        [,][@separator =] 'separator'] 
        [,][@echo_error =] 'echo_value'] 
        [,][@set_user =] 'user'] 
        [,][@dbuse =] 'database'] 

其中@recipients是必需的 

参数说明:

@recipients 收件人,中间用逗号分开 
@message 要发送的信息 
@query 确定执行并依附邮件的有效查询,除触发器中的插入表及删除表外,此查询能引用任何对象 
@attachments 附件 
@copy_recipients 抄送 
@blind_copy_recipients 密送 
@subject 标题 
@attach_results 指定查询结果做为附件发送 
@no_header 不发送查询结果的列名 
@set_user 查询联接的用户名,默认为Guset 
@dbuse 查询所用的数据库,默认为缺省数据库  

7.不过,如果是在web应用中使用SQL mail,还有一些问题要解决:首先,就是应用程序中连接数据库的账号,我在网站程序中的数据库连接是使用UDL文件,账号为DbGuest,这是一个普通帐户,所以还必须在master库的扩展存储过程找到XP_sendmail,并在其属性中增加DbGuest这个用户,并选择EXEC权限。

SQL服务器外网IP测试故障解决
  问:我的SQL服务器在用UDL文件进行SQL SERVER连接测试时(测试是在SQL服务器上)
  用别名和127.0.0.1都可以测试连接成功,但是用服务器的外网IP就可以连接
  此服务器为商用专用服务器..系统为win2000 server sp4
  请问是什么原因?
  如果用外网连接不上,我就不可以远程连上服务器了,急求解

   答:ping <服务器IP地址/服务器名称>
  如果 ping <服务器IP地址> 不成功,说明物理连接有问题,这时候要检查硬件设备,如网卡,HUB,路由器等.
  还有一种可能是由于客户端和服务器之间安装有防火墙软件造成的,比如 ISA Server.防火墙软件可能会屏蔽对 ping,telnet 等的响应
  因此在检查连接问题的时候,我们要先把防火墙软件暂时关闭,或者打开所有被封闭的端口.
  如果ping <服务器IP地址> 成功而,ping <服务器名称> 失败
  则说明名字解析有问题,这时候要检查 DNS 服务是否正常.
  有时候客户端和服务器不在同一个局域网里面,这时候很可能无法直接使用服务器名称来标识该服务器,这时候我们可以使用HOSTS文件来进行名字解析,
  具体的方法是:
  1.使用记事本打开HOSTS文件(一般情况下位于C:/WINNT/system32/drivers/etc).
  添加一条IP地址与服务器名称的对应记录,如:
  172.168.10.24 myserver
  2.或在 SQL Server 的客户端网络实用工具里面进行配置,后面会有详细说明.
============= 其次,使用 telnet 命令检查SQL Server服务器工作状态 =============
  telnet <服务器IP地址> 1433
  如果命令执行成功,可以看到屏幕一闪之后光标在左上角不停闪动,这说明 SQL Server 服务器工作正常,并且正在监听1433端口的 TCP/IP 连接
  如果命令返回"无法打开连接"的错误信息,则说明服务器端没有启动 SQL Server 服务,
  也可能服务器端没启用 TCP/IP 协议,或者服务器端没有在 SQL Server 默认的端口1433上监听.

  =============接着,我们要到服务器上检查服务器端的网络配置,检查是否启用了命名管道.是否启用了 TCP/IP 协议等等 =============
  可以利用 SQL Server 自带的服务器网络使用工具来进行检查.
  点击:程序 -- Microsoft SQL Server -- 服务器网络使用工具
  打开该工具后,在"常规"中可以看到服务器启用了哪些协议.
  一般而言,我们启用命名管道以及 TCP/IP 协议.
  点中 TCP/IP 协议,选择"属性",我们可以来检查 SQL Server 服务默认端口的设置。一般而言,我们使用 SQL Server 默认的1433端口.如果选中"隐藏服务器",则意味着客户端无法通过枚举服务器来看到这台服务器,起到了保护的作用,但不影响连接.

  =========== 接下来我们要到客户端检查客户端的网络配置 ==========
  我们同样可以利用 SQL Server 自带的客户端网络使用工具来进行检查,
  所不同的是这次是在客户端来运行这个工具.
  点击:程序 -- Microsoft SQL Server -- 客户端网络使用工具
  打开该工具后,在"常规"项中,可以看到客户端启用了哪些协议.
  一般而言,我们同样需要启用命名管道以及 TCP/IP 协议.
  点击 TCP/IP 协议,选择"属性",可以检查客户端默认连接端口的设置,该端口必须与服务器一致.
  单击"别名"选项卡,还可以为服务器配置别名.服务器的别名是用来连接的名称,
  连接参数中的服务器是真正的服务器名称,两者可以相同或不同.别名的设置与使用HOSTS文件有相似之处.
  通过以上几个方面的检查,基本上可以排除第一种错误.
  ----------------------------------------------------------------------------
 二."无法连接到服务器,用户xxx登陆失败"
  该错误产生的原因是由于SQL Server使用了"仅 Windows"的身份验证方式,
  因此用户无法使用SQL Server的登录帐户(如 sa )进行连接.解决方法如下所示:
  1.在服务器端使用企业管理器,并且选择"使用 Windows 身份验证"连接上 SQL Server
  在企业管理器中
  --右键你的服务器实例(就是那个有绿色图标的)
  --编辑SQL Server注册属性
  --选择"使用windows身份验证"
  2.展开"SQL Server组",鼠标右键点击SQL Server服务器的名称,选择"属性",再选择"安全性"选项卡
  3.在"身份验证"下,选择"SQL Server和 Windows ".
  4.重新启动SQL Server服务.
  在以上解决方法中,如果在第 1 步中使用"使用 Windows 身份验证"连接 SQL Server 失败,那就通过修改注册表来解决此问题:
  1.点击"开始"-"运行",输入regedit,回车进入注册表编辑器
  2.依次展开注册表项,浏览到以下注册表键:
  [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/MSSQLServer]
  3.在屏幕右方找到名称"LoginMode",双击编辑双字节值
  4.将原值从1改为2,点击"确定"
  5.关闭注册表编辑器
  6.重新启动SQL Server服务.
  此时,用户可以成功地使用sa在企业管理器中新建SQL Server注册,
  但是仍然无法使用Windows身份验证模式来连接SQL Server.
  这是因为在 SQL Server 中有两个缺省的登录帐户:
  BUILTIN/Administrators
  <机器名>/Administrator 被删除.
  要恢复这两个帐户,可以使用以下的方法:
  1.打开企业管理器,展开服务器组,然后展开服务器
  2.展开"安全性",右击"登录",然后单击"新建登录"
  3.在"名称"框中,输入 BUILTIN/Administrators
  4.在"服务器角色"选项卡中,选择"System Administrators"
  5.点击"确定"退出
  6.使用同样方法添加 <机器名>/Administrator 登录.
说明:
  以下注册表键:
  HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/MSSQLServer/LoginMode
  的值决定了SQL Server将采取何种身份验证模式.
  1.表示使用"Windows 身份验证"模式
  2.表示使用混合模式(Windows 身份验证和 SQL Server 身份验证).

  -----------------------------------------------------------------------------
  三.提示连接超时
  如果遇到第三个错误,一般而言表示客户端已经找到了这台服务器,并且可以进行连接,不过是由于连接的时间大于允许的时间而导致出错。这种情况一般会发生在当用户在Internet上运行企业管理器来注册另外一台同样在Internet上的服务器,并且是慢速连接时,有可能会导致以上的超时错误.有些情况下,由于局域网的网络问题,也会导致这样的错误.
  要解决这样的错误,可以修改客户端的连接超时设置。默认情况下,通过企业管理器注册另外一台SQL Server的超时设置是 4 秒,而查询分析器是 15 秒(这也是为什么在企业管理器里发生错误的可能性比较大的原因).
  具体步骤为:
  企业管理器中的设置:
  1.在企业管理器中,选择菜单上的"工具",再选择"选项"
  2.在弹出的"SQL Server企业管理器属性"窗口中,点击"高级"选项卡
  3.在"连接设置"下的"登录超时(秒)"右边的框中输入一个比较大的数字,如 20.
  查询分析器中的设置:
  工具 -- 选项 -- 连接 -- 将登录超时设置为一个较大的数字

SQL Server语句做数值大小比较的实现
问:sql server里
  我有①、②二张表:
  ①表有一个字段。通过条件查询出来其中一个字段的返回值。
  ②表有二个字段。通过条件查询出来其中2个字段的返回值,并将其值相加。
  然后把①、②表的返回值做数字的大小比较。
  如果返回①表的值大于②表的值,则返回“错误”的提示。
  反之,则报正常。
  怎么写这个sql语句?

   答:
  create table t1
  (
  idd varchar(10) not null,
  value int not null
  )
  create table t2
  (
  idd varchar(10) not null,
  value1 int not null,
  value2 int not null
  )
  insert into t1
  select '1', 10
  union all
  select '2', 20
  insert into t2
  select '1', 3, 5
  union all
  select '2', 12, 9
  declare @Res varchar(10)
  select @Res = case  when ((select t1.value from t1 where idd='2')  > (select value=t2.value1+t2.value2 from t2 where idd='2') )
  then '错误' else '正确' end
  select @Res
  drop table t1
  drop table t2
  /*结果
  正确
  */
如何在SQL Server中插入时间类型的数据
问:如在Oracle中有以下的语句:
INSERT INTO mytable (id,time) VALUES (100,to_date('2005-3-23 11:23:25','YYYY-MM-DD HH24:MI:SS'));
但是sql server不支持to_date
  最好能给个例子。
  答:
create table simp
(
 id int,
 time datetime   --SQL里自带时间格式
)
insert into simp(id,time) values (100,'2005-3-23 11:23:25')
go
select * from simp
drop table simp
  决定输入的日期如何解释的是set dateformat设置
  SET DATEFORMAT
  设置用于输入 datetime 或 smalldatetime 数据的日期部分(月/日/年)的顺序。
  语法
  SET DATEFORMAT { format | @format_var }
  参数
  format | @format_var
  是日期部分的顺序。可以是 Unicode 或转换为 Unicode 的 DBCS。有效参数包括 mdy、dmy、ymd、ydm、myd 和 dym。美国英语默认值是 mdy。
  注释
  该设置仅用在将字符串转换为日期值时的解释中。它对日期值的显示没有影响。
  SET DATEFORMAT 的设置是在执行或运行时设置,而不是在分析时设置。
  权限
  SET DATEFORMAT 权限默认授予所有用户。
  示例
  下例使用不同的日期格式处理不同格式的日期字符串。
SET DATEFORMAT mdy
GO
DECLARE @datevar datetime
SET @datevar = '12/31/98'
SELECT @datevar
GO
SET DATEFORMAT ydm
GO
DECLARE @datevar datetime
SET @datevar = '98/31/12'
SELECT @datevar
GO
SET DATEFORMAT ymd
GO
DECLARE @datevar datetime
SET @datevar = '98/12/31'
SELECT @datevar
GO
局域网SQL Server实例调试问题
  问:局域网内的两台装有MSDE2000的电脑在SQL Server 服务管理器里只能看到自己的实例,却看不到对方的实例,只有对方的电脑名,是怎么回事? 具体情况如下:
  局域网是通的,能够ping通对方电脑的名称和IP。用MSDE2000在局域网的两台电脑分别安装了一个数据库实例,实例名不是缺省的计算机名,安装正常。在桌面右下角的SQL Server服务管理器的服务器一栏中,自己电脑的服务器实例名能显示出来,也能正常运行。但是,另一台电脑的服务器实例名没有显示,只显示另一台电脑的计算机名,这台电脑也不能正确连接另一台电脑上安装的数据库。在另一台电脑上也是这样情况,请问是怎么回事?如何解决?
   答:需要分情况看这个问题。
   一、如果两台机器都安装SQLServer后,再装的MSDE2000:
    1,在服务器组中右键,选择“新建SQL Server 注册”
    2,按提示点“下一步”
    3,添加服务器(你局域网内的服务器,系统会自动搜索)。
    4,选择“SQL身分验证模式”
    5,输入你的用户名和密码,例如如用户名: Sa .你也可以选择“连接时提示输入SQL
      登录信息”。
    6, 然后连续“下一步”完成添加。
  SQL Server没有注册不能使用远程服务器.
 二、如果没有安装SQL Server,只安装了MSDE,不能在企业管理器里进行注册:
  方法一:试一试用ODBC能够联过去吗?你装MSDE的话,是不是还用前台的程序连接,要是有的话,你试一试用IP连接。
  MSDE的身份验证是可以在注册表中修改的,你也可以试一试!
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/MSSQLServer下的loginmode
  方法二:再装一个企业管理器的
如果用t-sql语句,可用下面的
sp_addserver
定义远程服务器或本地 Microsoft&reg; SQL Server&#8482; 的名称。提供 sp_addserver 是为向后兼容。请使用 sp_addlinkedserver。
语法
sp_addserver [ @server = ] 'server'
    [ , [ @local = ] 'local' ]
    [ , [ @duplicate_ok = ] 'duplicate_OK' ]
参数
[@server =] 'server'
服务器的名称。虽然不允许使用空格,但是服务器的名称必须是唯一的,而且遵循 Microsoft Windows NT&reg; 计算机名称的规则。server 是的数据类型为 sysname,无默认设置。
如果计算机上安装了多个 SQL Server 实例,则实例将如同在一个独立服务器上运行。通过以下列格式引用服务器来指定命名实例:servername/instancename。
[@local =] 'LOCAL'
指定要添加的服务器是本地服务器还是远程服务器。@local 的数据类型为 varchar(10),默认值为 NULL。指定 @local 为 LOCAL 将定义 @server 为本地服务器的名称并使 @@SERVERNAME 函数返回 server。(在安装过程中,安装程序将该变量设置为计算机名。建议不要更改该名称。默认情况下,用户可通过计算机名连接到 SQL Server 而无需额外的配置。)只有将服务器关闭然后重新启动后,本地的定义才会生效。每个服务器中只能定义一个本地服务器。
[@duplicate_ok =] 'duplicate_OK'
指定是否允许重复的服务器名。@duplicate_OK 的数据类型为 varchar(13),默认值为 NULL。@duplicate_OK 只能有 duplicate_OK 或 NULL 这两个值。如果指定了 duplicate_OK,则即使要添加的服务名已经存在,也不会发生错误。如果没有使用命名参数,则必须指定 @local。
返回代码值
0(成功)或 1(失败)
注释
若要执行运行较早版本的 SQL Server 的远程服务器上的存储过程(远程过程调用),请使用 sp_addserver 添加远程服务器。若要执行运行 SQL Server 7.0 的远程服务器上的存储过程(或任何分布式查询),请使用 sp_addlinkedserver 添加服务器。
若要设置或清除服务器选项,请使用 sp_serveroption。
在用户定义的事务内不能使用 sp_addserver。
权限
只有 setupadmin 和 sysadmin 固定服务器角色的成员才能执行 sp_addserver。
示例
下面的示例在本地服务器上为远程服务器 ACCOUNTS 创建一个条目。
sp_addserver 'ACCOUNTS'
SQL Server数据库六种数据移动方法
 本人从事的工作是数据库管理员,要维护多台服务器中的数据库,经常把某台服务器中的某个数据库移动到另外一台服务器,对数据的移动有些心得体会,希望和大家共同交流。

  1. 通过工具DTS的设计器进行导入或导出DTS的设计器功能强大,支持多任务,也是可视化界面,容易操作,但知道的人一般不多,如果只是进行SQL Server数据库中部分表的移动,用这种方法最好,当然,也可以进行全部表的移动。在SQL Server Enterprise Manager中,展开服务器左边的+,选择数据库,右击,选择All tasks/Import Data...(或All tasks/Export Data...),进入向导模式,按提示一步一步走就行了,里面分得很细,可以灵活的在不同数据源之间复制数据,很方便的。而且可以另存成DTS包,如果以后还有相同的复制任务,直接运行DTS包就行,省时省力。也可以直接打开DTS设计器,方法是展开服务器名称下面的Data Transformation Services,选Local Packages,在右边的窗口中右击,选New Package,就打开了DTS设计器。值得注意的是:如果源数据库要拷贝的表有外键,注意移动的顺序,有时要分批移动,否则外键主键,索引可能丢失,移动的时候选项旁边的提示说的很明白,或者一次性的复制到目标数据库中,再重新建立外键,主键,索引。

  其实建立数据库时,建立外键,主键,索引的文件应该和建表文件分开,而且用的数据文件也分开,并分别放在不同的驱动器上,有利于数据库的优化。

  2. 利用Bcp工具

  这种工具虽然在SQL Server7的版本中不推荐使用,但许多数据库管理员仍很喜欢用它,尤其是用过SQL Server早期版本的人。Bcp有局限性,首先它的界面不是图形化的,其次它只是在SQL Server的表(视图)与文本文件之间进行复制,但它的优点是性能好,开销小,占用内存少,速度快。有兴趣的朋友可以查参考手册。

  3. 利用备份和恢复

  先对源数据库进行完全备份,备份到一个设备(device)上,然后把备份文件复制到目的服务器上(恢复的速度快),进行数据库的恢复操作,在恢复的数据库名中填上源数据库的名字(名字必须相同),选择强制型恢复(可以覆盖以前数据库的选项),在选择从设备中进行恢复,浏览时选中备份的文件就行了。这种方法可以完全恢复数据库,包括外键,主键,索引。

  4. 直接拷贝数据文件

  把数据库的数据文件(*.mdf)和日志文件(*.ldf)都拷贝到目的服务器,在SQL Server Query Analyzer中用语句进行恢复:

EXEC sp_attach_db @dbname = 'test',

@filename1 = 'd:/mssql7/data/test_data.mdf',

@filename2 = 'd:/mssql7/data/test_log.ldf'

  这样就把test数据库附加到SQL Server中,可以照常使用。如果不想用原来的日志文件,可以用如下的命令:

EXEC sp_detach_db @dbname = 'test'

EXEC sp_attach_single_file_db @dbname = 'test',

@physname = 'd:/mssql7/data/test_data.mdf'

  这个语句的作用是仅仅加载数据文件,日志文件可以由SQL Server数据库自动添加,但是原来的日志文件中记录的数据就丢失了。

  5. 在应用程序中定制

  可以在应用程序(PB、VB)中执行自己编写的程序,也可以在Query Analyzer中执行,这种方法比较灵活,其实是利用一个平台连接到数据库,在平台中用的主要时SQL语句,这种方法对数据库的影响小,但是如果用到远程链接服务器,要求网络之间的传输性能好,一般有两种语句:

1> select ... into new_tablename where ...

2> insert (into) old_tablename select ... from ... where ...

  区别是前者把数据插入一个新表(先建立表,再插入数据),后者是把数据插入已经存在的一个表中,我个人喜欢后者,因为在编程的结构上,应用的范围上,第二条语句强于前者。

  6. SQL Server的复制功能

  SQL Server提供了强大的数据复制功能,也是最不易掌握的,具体应用请参考相关资料,值得注意的是要想成功进行数据的复制工作,有些条件是必不可少的:

1>SQL Server Agent必须启动,MSDTC必须启动。

2>所有要复制的表必须有主键。

3>如果表中有text或image数据类型,必须使用with log选项,不能使用with no_log选项。

另外max text repl size选项控制可以复制的文本和图像数据的最大规模,超过这个限制的操作将失败。

4>在要进行复制的计算机上,应该至少是隐含共享,即共享名是C$或D$…。

5>为SQL Server代理使用的Windows NT帐号不能是一个本地的系统帐号,因为本地的系统帐号不允许网络存取。

6>如果参与复制的服务器在另外的计算机域中,必须在这些域之间建立信任关系。
保护 SQL Server 的十个步骤
1.安装最新的服务包。
  为了提高服务器安全性,最有效的一个方法就是升级到 SQL Server 2000 Service Pack 3a (SP3a)。
  另外,您还应该安装所有已发布的安全更新。
 
  2.使用 Microsoft 基线安全性分析器(MBSA)来评估服务器的安全性。
  MBSA 是一个扫描多种 Microsoft 产品的不安全配置的工具,包括 SQL Server 和 Microsoft SQL Server 2000 Desktop Engine (MSDE 2000)。它可以在本地运行,也可以通过网络运行。该工具针对下面问题对 SQL Server 安装进行检测:
  1)   过多的sysadmin固定服务器角色成员。
  2)   授予sysadmin以外的其他角色创建 CmdExec 作业的权利。
  3)   空的或简单的密码。
  4)   脆弱的身份验证模式。
  5)   授予管理员组过多的权利。
  6)   SQL Server数据目录中不正确的访问控制表(ACL)。
  7)   安装文件中使用纯文本的sa密码。
  8)   授予guest帐户过多的权利。
  9)   在同时是域控制器的系统中运行SQL Server。
  10)  所有人(Everyone)组的不正确配置,提供对特定注册表键的访问。
  11)  SQL Server 服务帐户的不正确配置。
  12)  没有安装必要的服务包和安全更新。
 
  Microsoft 提供 MBSA 的免费下载。
 
  3.使用 Windows 身份验证模式。
  在任何可能的时候,您都应该对指向 SQL Server 的连接要求 Windows 身份验证模式。它通过限制对Microsoft Windows?用户和域用户帐户的连接,保护 SQL Server 免受大部分 Internet 的工具的侵害,而且,您的服务器也将从 Windows 安全增强机制中获益,例如更强的身份验证协议以及强制的密码复杂性和过期时间。另外,凭证委派(在多台服务器间桥接凭证的能力)也只能在 Windows 身份验证模式中使用。在客户端,Windows 身份验证模式不再需要存储密码。存储密码是使用标准 SQL Server 登录的应用程序的主要漏洞之一。
  要在 SQL Server 的 Enterprise Manager 安装 Windows 身份验证模式,请按下列步骤操作:
  1) 展开服务器组。
  2) 右键点击服务器,然后点击属性。
  3) 在安全性选项卡的身份验证中,点击仅限 Windows。
 
  4.隔离您的服务器,并定期备份。
  物理和逻辑上的隔离组成 了SQL Server 安全性的基础。驻留数据库的机器应该处于一个从物理形式上受到保护的地方,最好是一个上锁的机房,配备有洪水检测以及火灾检测/消防系统。数据库应该安装在企业内部网的安全区域中,不要直接连接到 Internet。定期备份所有数据,并将副本保存在安全的站点外地点。
 
  5.分配一个强健的sa密码。
  sa帐户应该总拥有一个强健的密码,即使在配置为要求 Windows 身份验证的服务器上也该如此。这将保证在以后服务器被重新配置为混合模式身份验证时,不会出现空白或脆弱的sa。
  要分配sa密码,请按下列步骤操作:
  1) 展开服务器组,然后展开服务器。
  2) 展开安全性,然后点击登录。
  3) 在细节窗格中,右键点击SA,然后点击属性。
  4) 在密码方框中,输入新的密码。
6.限制 SQL Server服务的权限。
  SQL Server 2000 和 SQL Server Agent 是作为 Windows 服务运行的。每个服务必须与一个 Windows 帐户相关联,并从这个帐户中衍生出安全性上下文。SQL Server允许sa 登录的用户(有时也包括其他用户)来访问操作系统特性。这些操作系统调用是由拥有服务器进程的帐户的安全性上下文来创建的。如果服务器被攻破了,那么这些操作系统调用可能被利用来向其他资源进行攻击,只要所拥有的过程(SQL Server服务帐户)可以对其进行访问。因此,为 SQL Server 服务仅授予必要的权限是十分重要的。
  我们推荐您采用下列设置:
  1) SQL Server Engine/MSSQLServer
  如果拥有指定实例,那么它们应该被命名为MSSQL$InstanceName。作为具有一般用户权限的Windows 域用户帐户运行。不要作为本地系统、本地管理员或域管理员帐户来运行。
  2) SQL Server Agent Service/SQLServerAgent
  如果您的环境中不需要,请禁用该服务;否则请作为具有一般用户权限的Windows域用户帐户运行。不要作为本地系统、本地管理员或域管理员帐户来运行。
  重点: 如果下列条件之一成立,那么 SQL Server Agent 将需要本地 Windows管理员权限:
   SQL Server Agent 使用标准的 SQL Server 身份验证连接到SQL Server(不推荐)。
   SQL Server Agent 使用多服务器管理主服务器(MSX)帐户,而该帐户使用标准 SQL Server 身份验证进行连接。
   SQL Server Agent 运行非sysadmin固定服务器角色成员所拥有的 Microsoft ActiveX?脚本或 CmdExec 作业。
  如果您需要更改与 SQL Serve r服务相关联的帐户,请使用 SQL Server Enterprise Manager。Enterprise Manager 将为 SQL Server 所使用的文件和注册表键设置合适的权限。不要使用 Microsoft 管理控制台的"服务"(在控制面板中)来更改这些帐户,因为这样需要手动地调制大量的注册表键和NTFS文件系统权限以及Micorsoft Windows用户权限。
  帐户信息的更改将在下一次服务启动时生效。如果您需要更改与 SQL Server 以及 SQL Server Agent 相关联的帐户,那么您必须使用 Enterprise Manager 分别对两个服务进行更改。
  
  7.在防火墙上禁用 SQL Server 端口。
  SQL Server 的默认安装将监视 TCP 端口 1433 以及UDP端口 1434。配置您的防火墙来过滤掉到达这些端口的数据包。而且,还应该在防火墙上阻止与指定实例相关联的其他端口。
 
  8.使用最安全的文件系统。
  NTFS 是最适合安装 SQL Server 的文件系统。它比 FAT 文件系统更稳定且更容易恢复。而且它还包括一些安全选项,例如文件和目录 ACL 以及文件加密(EFS)。在安装过程中,如果侦测到 NTFS,SQL Server 将在注册表键和文件上设置合适的 ACL。不应该去更改这些权限。
  通过 EFS,数据库文件将在运行 SQL Server 的帐户身份下进行加密。只有这个帐户才能解密这些文件。如果您需要更改运行 SQL Server 的帐户,那么您必须首先在旧帐户下解密这些文件,然后在新帐户下重新进行加密。
 
  9.删除或保护旧的安装文件。
  SQL Server 安装文件可能包含由纯文本或简单加密的凭证和其他在安装过程中记录的敏感配置信息。这些日志文件的保存位置取决于所安装的SQL Server版本。在 SQL Server 2000 中,下列文件可能受到影响:默认安装时<systemdrive>:/Program Files/Microsoft SQL Server/MSSQL/Install文件夹中,以及指定实例的<systemdrive>:/Program Files/Microsoft SQL Server/ MSSQL$<Instance Name>/Install文件夹中的sqlstp.log, sqlsp.log和setup.iss
  如果当前的系统是从 SQL Server 7.0 安装升级而来的,那么还应该检查下列文件:%Windir% 文件夹中的setup.iss以及Windows Temp文件夹中的sqlsp.log。
  Microsoft发布了一个免费的实用工具 Killpwd,它将从您的系统中找到并删除这些密码。
 
  10.审核指向 SQL Server 的连接。
  SQL Server 可以记录事件信息,用于系统管理员的审查。至少您应该记录失败的 SQL Server 连接尝试,并定期地查看这个日志。在可能的情况下,不要将这些日志和数据文件保存在同一个硬盘上。
  要在 SQL Server 的 Enterprise Manager 中审核失败连接,请按下列步骤操作:
  1) 展开服务器组。
  2) 右键点击服务器,然后点击属性。
  3) 在安全性选项卡的审核等级中,点击失败。
  4) 要使这个设置生效,您必须停止并重新启动服务器。
SQL Server实用经验技巧集
(一)挂起操作
  在安装Sql或sp补丁的时候系统提示之前有挂起的安装操作,要求重启,这里往往重启无用,解决办法:
  到HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager
  删除PendingFileRenameOperations
  (二)收缩数据库

   --重建索引
  DBCC REINDEX
  DBCC INDEXDEFRAG
  --收缩数据和日志
  DBCC SHRINKDB
  DBCC SHRINKFILE
 

  (三)压缩数据库

   dbcc shrinkdatabase(dbname)
 

  (四)转移数据库给新用户以已存在用户权限

   exec sp_change_users_login 'update_one','newname','oldname'
  go
 

  (五)检查备份集

   RESTORE VERIFYONLY from disk='E:/dvbbs.bak'
 

  (六)修复数据库

   ALTER DATABASE [dvbbs] SET SINGLE_USER
  GO
  DBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCK
  GO
  ALTER DATABASE [dvbbs] SET MULTI_USER
  GO
  --CHECKDB 有3个参数:
  --REPAIR_ALLOW_DATA_LOSS
 

  --  执行由 REPAIR_REBUILD 完成的所有修复,包括对行和页进行分配和取消分配以改正分配错误、结构行或页的错误,以及删除已损坏的文本对象。这些修复可能会导致一些数据丢失。修复操作可以在用户事务下完成以允许用户回滚所做的更改。如果回滚修复,则数据库仍会含有错误,应该从备份进行恢复。如果由于所提供修复等级的缘故遗漏某个错误的修复,则将遗漏任何取决于该修复的修复。修复完成后,备份数据库。
  --REPAIR_FAST 进行小的、不耗时的修复操作,如修复非聚集索引中的附加键。这些修复可以很快完成,并且不会有丢失数据的危险。
  --REPAIR_REBUILD 执行由 REPAIR_FAST 完成的所有修复,包括需要较长时间的修复(如重建索引)。执行这些修复时不会有丢失数据的危险。

   --DBCC CHECKDB('dvbbs') with NO_INFOMSGS,PHYSICAL_ONLY
 

  SQL SERVER日志清除的两种方法
  在使用过程中大家经常碰到数据库日志非常大的情况,在这里介绍了两种处理方法……
  方法一
  一般情况下,SQL数据库的收缩并不能很大程度上减小数据库大小,其主要作用是收缩日志大小,应当定期进行此操作以免数据库日志过大
  1、设置数据库模式为简单模式:打开SQL企业管理器,在控制台根目录中依次点开Microsoft SQL Server-->SQL Server组-->双击打开你的服务器-->双击打开数据库目录-->选择你的数据库名称(如论坛数据库Forum)-->然后点击右键选择属性-->选择选项-->在故障还原的模式中选择“简单”,然后按确定保存。
  2、在当前数据库上点右键,看所有任务中的收缩数据库,一般里面的默认设置不用调整,直接点确定。
  3、收缩数据库完成后,建议将您的数据库属性重新设置为标准模式,操作方法同第一点,因为日志在一些异常情况下往往是恢复数据库的重要依据
  方法二

   SET NOCOUNT ON
  DECLARE @LogicalFileName sysname,
  @MaxMinutes INT,
  @NewSize INT
  USE     tablename             -- 要操作的数据库名
  SELECT  @LogicalFileName = 'tablename_log',  -- 日志文件名
  @MaxMinutes = 10,               -- Limit on time allowed to wrap log.
  @NewSize = 1                  -- 你想设定的日志文件的大小(M)
 
 
   -- Setup / initialize
  DECLARE @OriginalSize int
  SELECT @OriginalSize = size
  FROM sysfiles
  WHERE name = @LogicalFileName
  SELECT 'Original Size of ' + db_name() + ' LOG is ' +
  CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' +
  CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
  FROM sysfiles
  WHERE name = @LogicalFileName
  CREATE TABLE DummyTrans
  (DummyColumn char (8000) not null)
 
 
   DECLARE @Counter   INT,
  @StartTime DATETIME,
  @TruncLog  VARCHAR(255)
  SELECT  @StartTime = GETDATE(),
  @TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'
  DBCC SHRINKFILE (@LogicalFileName, @NewSize)
  EXEC (@TruncLog)
  -- Wrap the log if necessary.
  WHILE     @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
  AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName) 
  AND (@OriginalSize * 8 /1024) > @NewSize 
  BEGIN -- Outer loop.
  SELECT @Counter = 0
  WHILE  ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))
  BEGIN -- update
  INSERT DummyTrans VALUES ('Fill Log') 
  DELETE DummyTrans
  SELECT @Counter = @Counter + 1
  END  
  EXEC (@TruncLog) 
  END  
  SELECT 'Final Size of ' + db_name() + ' LOG is ' +
  CONVERT(VARCHAR(30),size) + ' 8K pages or ' +
  CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
  FROM sysfiles
  WHERE name = @LogicalFileName
  DROP TABLE DummyTrans
  SET NOCOUNT OFF
删除数据库中重复数据的几个方法
  数据库的使用过程中由于程序方面的问题有时候会碰到重复数据,重复数据导致了数据库部分设置不能正确设置……
  方法一

   declare @max integer,@id integer
  declare cur_rows cursor local for select 主字段,count(*) from 表名 group by 主字段 having count(*) > 1
  open cur_rows
  fetch cur_rows into @id,@max
  while @@fetch_status=0
  begin
  select @max = @max -1
  set rowcount @max
  delete from 表名 where 主字段 = @id
  fetch cur_rows into @id,@max
  end
  close cur_rows
  set rowcount 0

  方法二
  有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如Name字段重复,而其他字段不一定重复或都重复可以忽略。
  1、对于第一种重复,比较容易解决,使用

   select distinct * from tableName
 

  就可以得到无重复记录的结果集。
  如果该表需要删除重复的记录(重复记录保留1条),可以按以下方法删除

   select distinct * into #Tmp from tableName
  drop table tableName
  select * into tableName from #Tmp
  drop table #Tmp
 
  发生这种重复的原因是表设计不周产生的,增加唯一索引列即可解决。
  2、这类重复问题通常要求保留重复记录中的第一条记录,操作方法如下
  假设有重复的字段为Name,Address,要求得到这两个字段唯一的结果集

   select identity(int,1,1) as autoID, * into #Tmp from tableName
  select min(autoID) as autoID into #Tmp2 from #Tmp group by Name,autoID
  select * from #Tmp where autoID in(select autoID from #tmp2)
 
  最后一个select即得到了Name,Address不重复的结果集(但多了一个autoID字段,实际写时可以写在select子句中省去此列)
  更改数据库中表的所属用户的两个方法
  大家可能会经常碰到一个数据库备份还原到另外一台机器结果导致所有的表都不能打开了,原因是建表的时候采用了当时的数据库用户……
  --更改某个表

   exec sp_changeobjectowner 'tablename','dbo'
 
  --存储更改全部表

   CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch
  @OldOwner as NVARCHAR(128),
  @NewOwner as NVARCHAR(128)
  AS
  DECLARE @Name   as NVARCHAR(128)
  DECLARE @Owner  as NVARCHAR(128)
  DECLARE @OwnerName  as NVARCHAR(128)
  DECLARE curObject CURSOR FOR
  select 'Name'   = name,
  'Owner'   = user_name(uid)
  from sysobjects
  where user_name(uid)=@OldOwner
  order by name
  OPEN  curObject
  FETCH NEXT FROM curObject INTO @Name, @Owner
  WHILE(@@FETCH_STATUS=0)
  BEGIN    
  if @Owner=@OldOwner
  begin
  set @OwnerName = @OldOwner + '.' + rtrim(@Name)
  exec sp_changeobjectowner @OwnerName, @NewOwner
  end
  -- select @name,@NewOwner,@OldOwner
  FETCH NEXT FROM curObject INTO @Name, @Owner
  END
  close curObject
  deallocate curObject
  GO
 
  SQL SERVER中直接循环写入数据
  没什么好说的了,大家自己看,有时候有点用处

   declare @i int
  set @i=1
  while @i<30
  begin
  insert into test (userid) values(@i)
  set @i=@i+1
  end
 
  无数据库日志文件恢复数据库方法两则
  数据库日志文件的误删或别的原因引起数据库日志的损坏

  方法一
  1.新建一个同名的数据库
  2.再停掉sql server(注意不要分离数据库)
  3.用原数据库的数据文件覆盖掉这个新建的数据库
  4.再重启sql server
  5.此时打开企业管理器时会出现置疑,先不管,执行下面的语句(注意修改其中的数据库名)
  6.完成后一般就可以访问数据库中的数据了,这时,数据库本身一般还要问题,解决办法是,利用
  数据库的脚本创建一个新的数据库,并将数据导进去就行了.

   USE MASTER
  GO
  SP_CONFIGURE 'ALLOW UPDATES',1 RECONFIGURE WITH OVERRIDE
  GO
  UPDATE SYSDATABASES SET STATUS =32768 WHERE NAME='置疑的数据库名'
  Go
  sp_dboption '置疑的数据库名', 'single user', 'true'
  Go
  DBCC CHECKDB('置疑的数据库名')
  Go
  update sysdatabases set status =28 where name='置疑的数据库名'
  Go
  sp_configure 'allow updates', 0 reconfigure with override
  Go
  sp_dboption '置疑的数据库名', 'single user', 'false'
  Go

  方法二
  事情的起因
  昨天,系统管理员告诉我,我们一个内部应用数据库所在的磁盘空间不足了。我注意到数据库事件日志文件XXX_Data.ldf文件已经增长到了3GB,于是我决意缩小这个日志文件。经过收缩数据库等操作未果后,我犯了一个自进入行业以来的最大最愚蠢的错误:竟然误删除了这个日志文件!后来我看到所有论及数据库恢复的文章上都说道:“无论如何都要保证数据库日志文件存在,它至关重要”,甚至微软甚至有一篇KB文章讲如何只靠日志文件恢复数据库的。我真是不知道我那时候是怎么想的?!
  这下子坏了!这个数据库连不上了,企业管理器在它的旁边写着“(置疑)”。而且最要命的,这个数据库从来没有备份了。我唯一找得到的是迁移半年前的另外一个数据库服务器,应用倒是能用了,但是少了许多记录、表和存储过程。真希望这只是一场噩梦!
  没有效果的恢复步骤
  附加数据库
  _Rambo讲过被删除日志文件中不存在活动日志时,可以这么做来恢复:
  1,分离被置疑的数据库,可以使用sp_detach_db
  2,附加数据库,可以使用sp_attach_single_file_db
  但是,很遗憾,执行之后,SQL Server质疑数据文件和日志文件不符,所以无法附加数据库数据文件。
  DTS数据导出
  不行,无法读取XXX数据库,DTS Wizard报告说“初始化上下文发生错误”。
  紧急模式
  怡红公子讲过没有日志用于恢复时,可以这么做:
  1,把数据库设置为emergency mode
  2,重新建立一个log文件
  3,把SQL Server 重新启动一下
  4,把应用数据库设置成单用户模式
  5,做DBCC CHECKDB
  6,如果没有什么大问题就可以把数据库状态改回去了,记得别忘了把系统表的修改选项关掉
  我实践了一下,把应用数据库的数据文件移走,重新建立一个同名的数据库XXX,然后停掉SQL服务,把原来的数据文件再覆盖回来。之后,按照怡红公子的步骤走。
  但是,也很遗憾,除了第2步之外,其他步骤执行非常成功。可惜,重启SQL Server之后,这个应用数据库仍然是置疑!
  不过,让我欣慰的是,这么做之后,倒是能够Select数据了,让我大出一口气。只不过,组件使用数据库时,报告说:“发生错误:-2147467259,未能在数据库 'XXX' 中运行 BEGIN TRANSACTION,因为该数据库处于回避恢复模式。”
  最终成功恢复的全部步骤
  设置数据库为紧急模式
  停掉SQL Server服务;
  把应用数据库的数据文件XXX_Data.mdf移走;
  重新建立一个同名的数据库XXX;
  停掉SQL服务;
  把原来的数据文件再覆盖回来;
  运行以下语句,把该数据库设置为紧急模式;

   运行“Use Master
  Go
  sp_configure 'allow updates', 1
  reconfigure with override
  Go”
 

  执行结果:
  DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
  已将配置选项 'allow updates' 从 0 改为 1。请运行 RECONFIGURE 语句以安装。
  接着运行“update sysdatabases set status = 32768 where name = 'XXX'”
  执行结果:
  (所影响的行数为 1 行)
  重启SQL Server服务;
  运行以下语句,把应用数据库设置为Single User模式;
  运行“sp_dboption 'XXX', 'single user', 'true'”
  执行结果:
  命令已成功完成。
  ü         做DBCC CHECKDB;
  运行“DBCC CHECKDB('XXX')”
  执行结果:
  'XXX' 的 DBCC 结果。
  'sysobjects' 的 DBCC 结果。
  对象 'sysobjects' 有 273 行,这些行位于 5 页中。
  'sysindexes' 的 DBCC 结果。
  对象 'sysindexes' 有 202 行,这些行位于 7 页中。
  'syscolumns' 的 DBCC 结果。
  ………
  ü         运行以下语句把系统表的修改选项关掉;

   运行“sp_resetstatus "XXX"
  go
  sp_configure 'allow updates', 0
  reconfigure with override
  Go”
 

  执行结果:
  在 sysdatabases 中更新数据库 'XXX' 的条目之前,模式 = 0,状态 = 28(状态 suspect_bit = 0),
  没有更新 sysdatabases 中的任何行,因为已正确地重置了模式和状态。没有错误,未进行任何更改。
  DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
  已将配置选项 'allow updates' 从 1 改为 0。请运行 RECONFIGURE 语句以安装。
  重新建立另外一个数据库XXX.Lost;
  DTS导出向导
  运行DTS导出向导;
  复制源选择EmergencyMode的数据库XXX,导入到XXX.Lost;
  选择“在SQL Server数据库之间复制对象和数据”,试了多次,好像不行,只是复制过来了所有表结构,但是没有数据,也没有视图和存储过程,而且DTS向导最后报告复制失败;
  所以最后选择“从源数据库复制表和视图”,但是后来发现,这样总是只能复制一部分表记录;
  于是选择“用一条查询指定要传输的数据”,缺哪个表记录,就导哪个;
  视图和存储过程是执行SQL语句添加的。
通过 SQL Server 访问注册表
使用扩展存储过程 xp_regread 和 xp_regwrite 来访问注册表。
  举例说明:
<%
Dim cnn
Dim rs
dim strSQL
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open "provider=sqloledb;data source=.;initial catalog=master;user id=sa;password=;"
strSQL = "xp_regread 'HKEY_LOCAL_MACHINE'," &_
 'SOFTWARE/Microsoft/Windows/Currentversion','CommonFilesDir'"
Set rs = cnn.Execute(strSQL)
Response.Write "Common files Path : " & rs("data")
rs.Close
Set rs = Nothing
cnn.Close
Set cnn = Nothing
%>
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
SQL Server加密存储过程的破解问题
有没有这样的SQL语句?
问:在一个姓名字段中,可以输入若干个人的姓名,每个人名用逗号来分开,字段数据如下:
CREATE PROCEDURE sp_decrypt(@objectName varchar(50))

AS
begin
set nocount on
--CSDN:j9988 copyright:2004.04.15
--V3.1
--破解字节不受限制,适用于SQLSERVER2000存储过程,函数,视图,触发器
--修正上一版视图触发器不能正确解密错误
--发现有错,请E_MAIL: CSDNj9988@tom.com
begin tran
declare @objectname1 varchar(100),@orgvarbin varbinary(8000)
declare @sql1 nvarchar(4000),@sql2 varchar(8000),@sql3 nvarchar(4000),@sql4 nvarchar(4000)
DECLARE @OrigSpText1 nvarchar(4000), @OrigSpText2 nvarchar(4000) , @OrigSpText3 nvarchar(4000), @resultsp nvarchar(4000)
declare @i int,@status int,@type varchar(10),@parentid int
declare @colid int,@n int,@q int,@j int,@k int,@encrypted int,@number int
select @type=xtype,@parentid=parent_obj from sysobjects where id=object_id(@ObjectName)
create table #temp(number int,colid int,ctext varbinary(8000),encrypted int,status int)
insert #temp SELECT number,colid,ctext,encrypted,status FROM syscomments WHERE id = object_id(@objectName)
select @number=max(number) from #temp
set @k=0
while @k<=@number
begin
if exists(select 1 from syscomments where id=object_id(@objectname) and number=@k)
begin
if @type='P'
set @sql1=(case when @number>1 then 'ALTER PROCEDURE '+ @objectName +';'+rtrim(@k)+' WITH ENCRYPTION AS '
else 'ALTER PROCEDURE '+ @objectName+' WITH ENCRYPTION AS '
end)
if @type='TR'
begin
declare @parent_obj varchar(255),@tr_parent_xtype varchar(10)
select @parent_obj=parent_obj from sysobjects where id=object_id(@objectName)
select @tr_parent_xtype=xtype from sysobjects where id=@parent_obj
if @tr_parent_xtype='V'
begin
set @sql1='ALTER TRIGGER '+@objectname+' ON '+OBJECT_NAME(@parentid)+' WITH ENCRYPTION INSTERD OF INSERT AS PRINT 1 '
end
else
begin
set @sql1='ALTER TRIGGER '+@objectname+' ON '+OBJECT_NAME(@parentid)+' WITH ENCRYPTION FOR INSERT AS PRINT 1 '
end
end
if @type='FN' or @type='TF' or @type='IF'
set @sql1=(case @type when 'TF' then
'ALTER FUNCTION '+ @objectName+'(@a char(1)) returns @b table(a varchar(10)) with encryption as begin insert @b select @a return end '
when 'FN' then
'ALTER FUNCTION '+ @objectName+'(@a char(1)) returns char(1) with encryption as begin return @a end'
when 'IF' then
'ALTER FUNCTION '+ @objectName+'(@a char(1)) returns table with encryption as return select @a as a'
end)
if @type='V'
set @sql1='ALTER VIEW '+@objectname+' WITH ENCRYPTION AS SELECT 1 as f'
set @q=len(@sql1)
set @sql1=@sql1+REPLICATE('-',4000-@q)
select @sql2=REPLICATE('-',8000)
set @sql3='exec(@sql1'
select @colid=max(colid) from #temp where number=@k
set @n=1
while @n<=CEILING(1.0*(@colid-1)/2) and len(@sQL3)<=3996
begin
set @sql3=@sql3+'+@'
set @n=@n+1
end
set @sql3=@sql3+')'
exec sp_executesql @sql3,N'@Sql1 nvarchar(4000),@ varchar(8000)',@sql1=@sql1,@=@sql2
end
set @k=@k+1
end
set @k=0
while @k< =@number
begin
上接: SQL Server加密存储过程的破解问题(1)
if exists(select 1 from syscomments where id=object_id(@objectname) and number=@k)
begin
select @colid=max(colid) from #temp where number=@k
set @n=1
while @n<=@colid
begin
select @OrigSpText1=ctext,@encrypted=encrypted,@status=status FROM #temp WHERE colid=@n and number=@k
SET @OrigSpText3=(SELECT ctext FROM syscomments WHERE id=object_id(@objectName) and colid=@n and number=@k)
if @n=1
begin
if @type='P'
SET @OrigSpText2=(case when @number>1 then 'CREATE PROCEDURE '+ @objectName +';'+rtrim(@k)+' WITH ENCRYPTION AS '
else 'CREATE PROCEDURE '+ @objectName +' WITH ENCRYPTION AS '
end)

if @type='FN' or @type='TF' or @type='IF'
SET @OrigSpText2=(case @type when 'TF' then
'CREATE FUNCTION '+ @objectName+'(@a char(1)) returns @b table(a varchar(10)) with encryption as begin insert @b select @a return end '
when 'FN' then
'CREATE FUNCTION '+ @objectName+'(@a char(1)) returns char(1) with encryption as begin return @a end'
when 'IF' then
'CREATE FUNCTION '+ @objectName+'(@a char(1)) returns table with encryption as return select @a as a'
end)
if @type='TR'
begin
if @tr_parent_xtype='V'
begin
set @OrigSpText2='CREATE TRIGGER '+@objectname+' ON '+OBJECT_NAME(@parentid)+' WITH ENCRYPTION INSTEAD OF INSERT AS PRINT 1 '
end
else
begin
set @OrigSpText2='CREATE TRIGGER '+@objectname+' ON '+OBJECT_NAME(@parentid)+' WITH ENCRYPTION FOR INSERT AS PRINT 1 '
end
end
if @type='V'
set @OrigSpText2='CREATE VIEW '+@objectname+' WITH ENCRYPTION AS SELECT 1 as f'
set @q=4000-len(@OrigSpText2)
set @OrigSpText2=@OrigSpText2+REPLICATE('-',@q)
end
else
begin
SET @OrigSpText2=REPLICATE('-', 4000)
end
SET @i=1
SET @resultsp = replicate(N'A', (datalength(@OrigSpText1) / 2))
WHILE @i<=datalength(@OrigSpText1)/2
BEGIN
SET @resultsp = stuff(@resultsp, @i, 1, NCHAR(UNICODE(substring(@OrigSpText1, @i, 1)) ^
(UNICODE(substring(@OrigSpText2, @i, 1)) ^
UNICODE(substring(@OrigSpText3, @i, 1)))))
SET @i=@i+1
END
set @orgvarbin=cast(@OrigSpText1 as varbinary(8000))
set @resultsp=(case when @encrypted=1
then @resultsp
else convert(nvarchar(4000),case when @status&2=2 then uncompress(@orgvarbin) else @orgvarbin end)
end)
print @resultsp
set @n=@n+1
end
end
set @k=@k+1
end
drop table #temp
rollback tran
end
如何使触发器具备良好的性能?
通过SET NOCOUNT ON 命令使触发器具有更好的性能
  触发器使得表和跨数据库之间数据的自动同步行为变得简单。但是,那些一眼看上去不是很明显的东西却会对它们的性能造成显著的影响。这里我将描述一个命令,它可用来减少一些不可预料的问题产生的影响 。
  以反复被触发的INSERT触发器为例,尤其是当使用INSERT INTO语句用来进行大量插入操作时。在语句执行的过程中,当触发器一遍又一遍的被激发的情况下,触发器将会对每个INSERT动作发布DONE_IN_PROC消息,这会使速度明显下降。
  尤其是当触发器作为一个预定了时间的SQL Server Agent工作的结果而被触发时,这个速度的减慢是特别明显的 。SQL Server Agent自动在每个DONE_IN_PROC 信号后强加一个延迟,以避免服务器拥塞 。如果你想通过查询分析器来运行同样的一组命令,由于没有强加这样的延迟,它的执行将会快得多。如果你通过查询分析器运行这样的查询并且查看多个语句产生的多个"n rows affected",那么很有可能查询会被反复执行,并且触发器也被重新触发多次,这比它实际需要的次数要多很多。
  要关掉DONE_IN_PROC消息,可以在触发器语句的开始用SET NOCOUNT ON命令。大多数时候,以任何方式对行进行计数都是不需要的。如果确实需要,你可以考虑重新构造命令来触发触发器(或者是触发器本身),这样就使所有的改变作为一个命令完成。如果这个进程仍然花了很长时间,为了简单起见,你应该重新想一个方法来激发触发器。
如何提高SQL Server 的安全性?
请问专家:在网上看到SQL Server的安全性令人担忧,我想知道如何才能使我的SQL Server数据库尽可能的安全?
 
  有一些步骤你可以用来使 SQL Server 数据库对篡改数据和黑客攻击更有抵抗力。其中一些是好的服务器管理中的简单的部分,例如使 SQL Server 保持最新的补丁,而另一些则涉及了一些用户在使用中的监控。下面的这五个步骤将带你开始这项工作。
 
  查找最新的服务程序包
  时刻确保你装了最新的服务程序包。对于 SQL Server 2000, 这个补丁是 SP3a 。记住,服务程序包是渐增的,所以如果你应用了 SP3a ,你就不需要再应用其他任何在此之前的程序包,例如 SP3, SP2 SP1 SP3a 是一个特殊的服务程序包,它是为那些没有进行过以前的任何更新而设计的安装程序,而 SP3 则是为那些已经安装了 SP1 SP2 准备的安装程序。
 
  使用安全警报
  补丁能够帮助你保护你的 SQL Server 数据库免受许多威胁,但是他们的发布速度总是跟不上那些移动迅速的安全性问题的处理,例如 Spammer 蠕虫。所以你就会想要使用微软公司的免费的安全通知服务,一封电子邮件服务就可以使你了解关于破坏安全的问题和怎样处理它们。
 
  运行微软的基线安全分析器( MBSA
  这个工具对于 SQL Server MSDE 2000 Desktop Engine 都是可用的,并且它可以在本地运行,也可以在网络中运行。它寻找密码,访问权限,访问控制清单和注册的问题,并且检查遗漏的安全程序包或服务程序包。你可以在 TechNet 上找到这个工具的相关信息。
 
  删除 SA 和旧密码
  人们犯的关于密码的最大的安全性错误就是对系统管理员 (SA) 密码不做任何修改。你可能很轻易的忽略安装文件中的剩余的配置信息,保护得很差的认证信息和其他一些敏感的数据就会遭黑客破坏。你必须删除在这个路经下的旧的安装文件: Program Files/Microsoft SQL Server/MSSQL/Install Program Files/Microsoft SQL Server/MSSQL$<instancename>/Install folders 。还有,可以使用 KILLPWD 应用程序来找旧的密码并且删除它们。 Knowledge Base 文章 263968 对这个问题做了详细的说明。
 
  监控连接
  连接可以告诉你谁试图访问 SQL Server ,所以监视和控制连接是保护数据库安全的一个非常好的方法。对于一个大型的活动的 SQL Server 数据库,可能会有太多的数据连接需要监控,但是监控失败的连接是非常有价值的,因为它们可能表现出使用的企图。你可以在企业管理器中在服务组上右击,然后选择 Properties ,记录下失败连接的日志。然后点击 Security 选项卡,在 Audit Level 下点击 Failure 来停止并重新启动服务器。
——————————————————————————————
  背景文章:
  SQL Server中动态和静态内存分配问题解答
SQL服务器有两种基本管理方法:动态分配和静态分配,用以控制程序可使用的内存数量。动态分配允许管理员声明一块内存的大小;考虑到它的实际使用, SQL 服务器可以分配给其需要占用的内存的最大值,并且(理论上)在没有使用内存的情况下将其释放。静态分配则是创建一块固定的内存空间,提供给 SQL Server 使用——不再进行分配。
 
  在默认情况下, SQL Server 被设置成动态分配,分配给其正在运行的计算机内所有可用的物理内存。许多管理员注意到 SQL Server 内存随时间的流逝被逐渐消耗殆尽时,其原因很可能是故障或是内存漏洞,但这个程序正是被设计成这样的。 SQL Server 就是要在任何可能的情况下在电脑中运行,并因此为达到其最佳性能而使用所有可用的内存。如果 SQL Server 在独立的机器中运行,那么就让它分配和释放其需要的内存吧。
 
  在一个小型商业服务器机器中, SQL 可能与其他程序,如 IIS ,同时运行,管理员或许尝试着进行设置,使 SQL Server 运行在一块固定大小的内存,目的是控制其不会占用用于共享的内存。但这并不一定能如愿以偿。一方面,将内存的最高限度设置得太低,并且没有分配给 SQL 服务器足够的可用内存来用作类似事务日志或查询执行的缓存,所有这些都很难办到。使 SQL 服务器得到执行操作所需内存的惟一方法就是换出其他的页面,这是个缓慢的过程。
  
  有许多方法可以计算出最好的内存分配。如果你有可预知的用户负载,依照用户所需的最大数目分配给他们。微软推荐至少用 4 MB 用作动态的最大空间,这已经成为一个可能的规则。如果你的用户负载变化范围很大——如以下情况,当你通过 IIS 的前端连接到公共的因特网来支持你的数据库服务的时候——实时的统计数据将会比仅凭猜测所作的工作帮助更大。在高峰期,把 SQL Server 的高速缓存命中率和每秒缺页率等性能数字搜集起来。如果这些数据表明 SQL Server 正在做大量的交换,那么增加最大内存空间直到交换逐渐减少。每秒一次或更多次的交换是有坏处的。
 
  另一种选择是使“为 SQL Server 预留物理内存”的选项可用,这可以防止 SQL Server 把已经分配给它的内存换出,即使当其他应用程序能够使用它时。这可以叫做是一把双刃剑:它既可以相当大程度的提高性能,也可能带来更大的性能损害。在有许多 RAM 可以共享的( 1 GB 或更多)的系统中,这是值得一试的,但是当有其他关键的进程可能突然需要大量的内存时,这种办法是不应该使用的。(并且如果需要的话, SQL Server 可能会被迫放弃一些它自己的内存)。如果 SQL Server 是在独立的机器上运行,用这种办法最佳化性能则是值得的。
 
SQL Server与Excel数据互导解答
从SQL Server中导入/导出 Excel 的基本方法


/*=================== 导入/导出 Excel 的基本方法 ===================*/

从Excel文件中,导入数据到SQL数据库中,很简单,直接用下面的语句:

/*===================================================================*/
--如果接受数据导入的表已经存在
insert into 表 select * from
OPENROWSET('MICROSOFT.JET.OLEDB.4.0'
,'Excel 5.0;HDR=YES;DATABASE=c:test.xls',sheet1$)

--如果导入数据并生成表
select * into 表 from
OPENROWSET('MICROSOFT.JET.OLEDB.4.0'
,'Excel 5.0;HDR=YES;DATABASE=c:test.xls',sheet1$)


/*===================================================================*/
--如果从SQL数据库中,导出数据到Excel,如果Excel文件已经存在,而且已经按照要接收的数据创建好表头,就可以简单的用:
insert into OPENROWSET('MICROSOFT.JET.OLEDB.4.0'
,'Excel 5.0;HDR=YES;DATABASE=c:test.xls',sheet1$)
select * from 表


--如果Excel文件不存在,也可以用BCP来导成类Excel的文件,注意大小写:
--导出表的情况
EXEC master..xp_cmdshell 'bcp 数据库名.dbo.表名 out "c:test.xls" /c -/S"服务器名" /U"用户名" -P"密码"'

--导出查询的情况
EXEC master..xp_cmdshell 'bcp "SELECT au_fname, au_lname FROM pubs..authors ORDER BY au_lname" queryout "c:test.xls" /c -/S"服务器名" /U"用户名" -P"密码"'


/*--说明:
c:test.xls 为导入/导出的Excel文件名.
sheet1$     为Excel文件的工作表名,一般要加上$才能正常使用.
--*/
--上面已经说过,用BCP导出的是类Excel文件,其实质为文本文件,

--要导出真正的Excel文件.就用下面的方法


/*--数据导出EXCEL

导出表中的数据到Excel,包含字段名,文件为真正的Excel文件
,如果文件不存在,将自动创建文件
,如果表不存在,将自动创建表
基于通用性考虑,仅支持导出标准数据类型
--邹建 2003.10--*/

/*--调用示例

p_exporttb @tbname='地区资料',@path='c:',@fname='aa.xls'
--*/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_exporttb]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_exporttb]
GO

create proc p_exporttb
@tbname sysname,   --要导出的表名
@path nvarchar(1000),   --文件存放目录
@fname nvarchar(250)='' --文件名,默认为表名
as
declare @err int,@src nvarchar(255),@desc nvarchar(255),@out int
declare @obj int,@constr nvarchar(1000),@sql varchar(8000),@fdlist varchar(8000)

--参数检测
if isnull(@fname,'')='' set @fname=@tbname+'.xls'

--检查文件是否已经存在
if right(@path,1)<>'' set @path=@path+''
create table #tb(a bit,b bit,c bit)
set @sql=@path+@fname
insert into #tb exec master..xp_fileexist @sql

--数据库创建语句
set @sql=@path+@fname
if exists(select 1 from #tb where a=1)
set @constr='DRIVER={Microsoft Excel Driver (*.xls)};DSN='''';READONLY=FALSE'
    +';CREATE_DB="   +';DATABASE='+@sql+'"'


--连接数据库
exec @err=sp_oacreate 'adodb.connection',@obj out
if @err<>0 goto lberr

exec @err=sp_oamethod @obj,'open',null,@constr
if @err<>0 goto lberr

/*--如果覆盖已经存在的表,就加上下面的语句
--创建之前先删除表/如果存在的话
select @sql='drop table ['+@tbname+']'
exec @err=sp_oamethod @obj,'execute',@out out,@sql
--*/

--创建表的SQL
select @sql='',@fdlist=''
select @fdlist=@fdlist+',['+a.name+']'
,@sql=@sql+',['+a.name+'] '
+case when b.name in('char','nchar','varchar','nvarchar') then
  'text('+cast(case when a.length>255 then 255 else a.length end as varchar)+')'
  when b.name in('tynyint','int','bigint','tinyint') then 'int'
  when b.name in('smalldatetime','datetime') then 'datetime'
  when b.name in('money','smallmoney') then 'money'
  else b.name end
FROM syscolumns a left join systypes b on a.xtype=b.xusertype
where b.name not in('image','text','uniqueidentifier','sql_variant','ntext','varbinary','binary','timestamp')
and object_id(@tbname)=id
select @sql='create table ['+@tbname
+']('+substring(@sql,2,8000)+')'
,@fdlist=substring(@fdlist,2,8000)
exec @err=sp_oamethod @obj,'execute',@out out,@sql
if @err<>0 goto lberr

exec @err=sp_oadestroy @obj

--导入数据
set @sql='openrowset(''MICROSOFT.JET.OLEDB.4.0'',''Excel 5.0;HDR=YES
  ;DATABASE='+@path+@fname+''',['+@tbname+'$])'

exec('insert into '+@sql+'('+@fdlist+') select '+@fdlist+' from '+@tbname)

return

lberr:
exec sp_oageterrorinfo 0,@src out,@desc out
lbexit:
select cast(@err as varbinary(4)) as 错误号
,@src as 错误源,@desc as 错误描述
select @sql,@constr,@fdlist
go
--上面是导表的,下面是导查询语句的.
/*--数据导出EXCEL

导出查询中的数据到Excel,包含字段名,文件为真正的Excel文件
,如果文件不存在,将自动创建文件
,如果表不存在,将自动创建表
基于通用性考虑,仅支持导出标准数据类型
--邹建 2004.10--*/

/*--调用示例

p_exporttb @sqlstr='select * from 地区资料'
,@path='c:',@fname='aa.xls',@sheetname='地区资料'
--*/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_exporttb]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_exporttb]
GO

create proc p_exporttb
@sqlstr varchar(8000),   --查询语句,如果查询语句中使用了order by ,请加上top 100 percent
@path nvarchar(1000),   --文件存放目录
@fname nvarchar(250),   --文件名
@sheetname varchar(250)='' --要创建的工作表名,默认为文件名
as
declare @err int,@src nvarchar(255),@desc nvarchar(255),@out int
declare @obj int,@constr nvarchar(1000),@sql varchar(8000),@fdlist varchar(8000)

--参数检测
if isnull(@fname,'')='' set @fname='temp.xls'
if isnull(@sheetname,'')='' set @sheetname=replace(@fname,'.','#')

--检查文件是否已经存在
if right(@path,1)<>'' set @path=@path+''
create table #tb(a bit,b bit,c bit)
set @sql=@path+@fname
insert into #tb exec master..xp_fileexist @sql

--数据库创建语句
set @sql=@path+@fname
if exists(select 1 from #tb where a=1)
set @constr='DRIVER={Microsoft Excel Driver (*.xls)};DSN='''';READONLY=FALSE'
    +';CREATE_DB="   +';DATABASE='+@sql+'"'

--连接数据库
exec @err=sp_oacreate 'adodb.connection',@obj out
if @err<>0 goto lberr

exec @err=sp_oamethod @obj,'open',null,@constr
if @err<>0 goto lberr

--创建表的SQL
declare @tbname sysname
set @tbname='##tmp_'+convert(varchar(38),newid())
set @sql='select * into ['+@tbname+'] from('+@sqlstr+') a'
exec(@sql)

select @sql='',@fdlist=''
select @fdlist=@fdlist+',['+a.name+']'
,@sql=@sql+',['+a.name+'] '
+case when b.name in('char','nchar','varchar','nvarchar') then
  'text('+cast(case when a.length>255 then 255 else a.length end as varchar)+')'
  when b.name in('tynyint','int','bigint','tinyint') then 'int'
  when b.name in('smalldatetime','datetime') then 'datetime'
  when b.name in('money','smallmoney') then 'money'
  else b.name end
FROM tempdb..syscolumns a left join tempdb..systypes b on a.xtype=b.xusertype
where b.name not in('image','text','uniqueidentifier','sql_variant','ntext','varbinary','binary','timestamp')
and a.id=(select id from tempdb..sysobjects where name=@tbname)
select @sql='create table ['+@sheetname
+']('+substring(@sql,2,8000)+')'
,@fdlist=substring(@fdlist,2,8000)

exec @err=sp_oamethod @obj,'execute',@out out,@sql
if @err<>0 goto lberr

exec @err=sp_oadestroy @obj

--导入数据
set @sql='openrowset(''MICROSOFT.JET.OLEDB.4.0'',''Excel 5.0;HDR=YES
  ;DATABASE='+@path+@fname+''',['+@sheetname+'$])'

exec('insert into '+@sql+'('+@fdlist+') select '+@fdlist+' from ['+@tbname+']')

set @sql='drop table ['+@tbname+']'
exec(@sql)
return

lberr:
exec sp_oageterrorinfo 0,@src out,@desc out
lbexit:
select cast(@err as varbinary(4)) as 错误号
,@src as 错误源,@desc as 错误描述
select @sql,@constr,@fdlist
go

  ID  姓名
  1   AB,ABC
  2   ABC,AAA,BBB
  3   ABA,AAA

  能不能有一个SQL语句,将姓名为AB的人查询出来,也就是只显示第1条纪录.
  不能用select * from 表名 where 姓名 like *AB* 因为会将ABA,ABC的纪录也显示出来,
  该怎样写?

   答:
  create table t
  (
  IDD int not null,
  姓名 varchar(30) not null
  )
  insert into t
  select '1', 'AB,ABC'
  union all
  select '2', 'ABC,AAA,BBB'
  union all
  select '3', 'ABA,AB'
  union all
  select '3', 'ABA,AAA'
  union all
  select '3', 'ABA,AB,ABCD'
  union all
  select '3', 'ABA,AAA'
  select * from t where substring(姓名,1,3)='AB,'  --所有AB开头的
  union all
  select * from t where substring(姓名,len(姓名)-2,len(姓名))=',AB' --所有AB结束的
  union all
  select * from t where 姓名 like'%,AB,%' --中间的
  drop table t
  /*结果
  1 AB,ABC
  3 ABA,AB
  3 ABA,AB,ABCD
  */
Microsoft SQL Server 的安全性控制策略
引言

  数据库的安全性是指保护数据库以防止不合法的使用所造成的数据泄露、更改或破坏。系统安全保护措施是否有效是数据库系统的主要指标之一。数据库的安全性和计算机系统的安全性,包括操作系统、网络系统的安全性是紧密联系、相互支持的。
对于数据库管理来说,保护数据不受内部和外部侵害是一项重要的工作。 Microsoft SQL Server 正日益广泛的使用于各部门内外,作为 SQL Server SQL Server 是指 Microsoft SQL Server, 下文同)的数据库系统管理员,需要深入的理解 SQL Server 的安全性控制策略,以实现管理安全性的目标。

  图 1 给出了 SQL Server 安全控制策略示意图。由图可见, SQL Server 的安全控制策略是一个层次结构系统的集合。只有满足上一层系统的安全性要求之后,才可以进入下一层。


1 SQL Server 安全性控制策略示意图

  各层 SQL Server 安全控制策略是通过各层安全控制系统的身份验证实现的。身份验证是指当用户访问系统时,系统对该用户的账号和口令的确认过程。身份验证的内容包括确认用户的账号是否有效、能否访问系统、能访问系统的哪些数据等。

  身份验证方式是指系统确认用户的方式。 SQL Server 系统是基于 Windows NT/2000 操作系统的,现在的 SQL Server 系统可以安装在 Windows 95 (需要安装 Winsock 升级软件)、 Windows 98 Windows ME 之上(此时,将没有第一层和第二层的安全性控制),但旧的 SQL Servers 系统只能运行在 Windows NT/2000 操作系统上。 Windows NT/2000 对用户有自己的身份验证方式,用户必须提供自己的用户名和相应的口令才能访问 Windows NT/2000 系统。

  这样 SQL Server 的安全系统可在任何服务器上通过两种方式实现: SQL Server Windows 结合使用( SQL Server and Windows )以及只使用 Windows Windows Only )。访问 Windows NT/2000 系统用户能否访问 SQL Server 系统就取决于 SQL Server 系统身份验证方式的设置。
   1. 用户标识与验证

  用户标示和验证是系统提供的最外层安全保护措施。其方法是由系统提供一定的方式让用户标示自己的名字或身份。每次用户要求进入系统时,由系统进行核对,通过鉴定后才提供机器使用权。

  对于获得上机权的用户若要使用数据库时数据库管理系统还要进行用户标识和鉴定。

  用户标识和鉴定的方法有很多种,而且在一个系统中往往是多种方法并举,以获得更强的安全性。常用的方法有:

  用一个用户名或者用户标识号来标明用户身份。系统内部纪录着所有合法用户的标识,系统验证此户是否合法用户,若是,则可以进入下一步的核实;若不是,则不能使用系统。

  为了进一步核实用户,系统常常要求用户输入口令( Password )。为保密起见,用户在终端上输入的口令不显示在屏幕上。系统核对口令以验证用户身份。

  用户标识与验证在 SQL Server 中对应的是 Windows NT/2000 登录账号和口令以及 SQL Server 用户登录账号和口令。
2. SQL Server 身份验证方式

  用户必须使用一个登录账号,才能连接到 SQL Server 中。 SQL Server 可以识别两类的身份验证方式,即: SQL Server 身份验证( SQL Server Authentication )方式和 Windows 身份验证( Windows Authentication )方式。这两种方式的结构如图 2 所示。这两种方式都有自己的登录账号类型。


2 SQL Server 系统身份验证方式示意图

  注意的是,如果在 Microsoft Windows95/98/ME 上使用 SQL Server Personal 版,作为 SQL Server 宿主的 Microsoft Windows95/98/ME 系统只能使用 SQL Server 登录。因此, Windows NT/2000 身份验证、域用户的账号和域组账号都是不可用的。

  当使用 SQL Server 身份验证方式时, SQL Server 系统管理员定义 SQL Server 账号和口令。当用户连接 SQL Serve 时,必须提供登录账号和口令。当使用 Windows 身份验证方式时,由 Windows NT/2000 账号或者组控制用户对 SQL Server 系统的访问。这时,用户不必提供 SQL Server Login 账号和口令就能连接到系统上。但是,在该用户连接之前, SQL Serve 系统管理员必须将 Windows NT/2000 账号或者 Windows NT/2000 组定义为 SQL Server 的有效登录账号。
3. 身份验证模式

  当 SQL Serve Windows NT/2000 上运行时,系统管理员必须指定系统的身份验证模式类型。 SQL Server 的身份验证模式有两种: Windows 身份验证( Windows Authentication )模式和混合模式( Mixed Mode )。身份验证模式和身份验证方式的关系是:

   Windows 身份验证模式 Windows 身份验证方式)

  混合模式 Windows 身份验证方式 SQL Server 身份验证方式)

   Windows 身份验证模式只允许使用 Windows 身份验证方式,这时用户无法以 SQL Server 的登录账号登录服务器。它要求用户登录到 Windows NT/2000 ,当用户访问 SQL Server 时,不用再次登录。虽然用户仍会被提示登录,但 SQL Server 的用户名会自动从用户网络登录 ID 中提取。而混合身份验证模式即允许使用 Windows NT/2000 身份验证方式,又允许使用 SQL Server 身份验证方式。它使用户既可以登录 SQL Server ,也可用 Windows NT/2000 的集成登录。

  集成登录只能在用命名管道连接客户机服务器时使用。当使用混合模式时,无论是使用 Windows NT/2000 身份验证方式的用户,还是使用 SQL Server 身份验证方式的用户,都可以连接到 SQL Server 系统上。也就是说:身份验证模式是对服务器来说的,而身份验证方式是对客户端来说的。
4. Windows 身份验证模式

   Windows 身份验证模式最适用于只在部门访问数据库的情况。与 SQL Server 身份验证方式相比, Windows 身份验证方式具有下列优点:提供了更多的功能,例如安全确认和口令加密、审核、口令失效、最小口令长度和账号锁定;通过增加单个登录账号,允许在 SQL Server 系统中增加用户组;允许用户迅速访问 SQL Server 系统,而不必使用另一个登录账号和口令。

   SQL Server 系统按照下列步骤处理 Windows 身份验证方式中的登录账号:

   1 )当用户连接到 Windows NT/2000 系统上时,客户机打开一个到 SQL Server 系统的委托连接。该委托连接将 Windows NT/2000 的组和用户账号传送到 SQL Server 系统中。因为客户机打开了一个委托连接,所以 SQL Server 系统知道 Windows NT/2000 已经确认该用户有效。

   2 )如果 SQL Server 系统在系统表 syslogins SQL Server 用户清单中找到该用户的 Windows NT/2000 用户账号或者组账号,就接受这次身份验证连接。这时, SQL Server 系统不需要重新验证口令是否有效,因为 Windows NT/2000 已经验证用户的口令是有效的。

   3 )在这种情况下,该用户的 SQL Server 系统登录账号即可以是 Windows NT/2000 的用户账号,也可以是 Windows NT/2000 组账号。当然,这些用户账号或者组账号都已定义为 SQL Server 系统登录账号。

   4 )如果多个 SQL Server 机器在一个域或者在一组信任域中,那么登录到单个网络域上,就可以访问全部的 SQL Server 机器。
   5. 混合模式

  混合模式最适合用于外界用户访问数据库或不能登录到 Windows 域时。

  混合方式的 SQL Server 身份验证方式有下列优点:混合方式允许非 Windows NT/2000 客户、 Internet 客户和混合的客户组连接到 SQL Server 中; SQL Server 身份验证方式又增加了一层基于 Windows 的安全保护。 SQL Server 按照下列步骤处理自己的登录账号:

   1. 当一个使用 SQL Server 账号和口令的用户连接 SQL Server 时, SQL Server 验证该用户是否在系统表 syslogins 中且其口令是否与以前纪录的口令匹配。

   2. 如果在系统表 syslogins 中没有该用户账号,那么这次身份验证失败,系统拒绝该用户的连接。
  结束语

   SQL Server 提供多层安全。在最外层, SQL Server 的登录安全性直接集成到 Widows NT/2000 的安全上,它允许 Windows NT 服务器验证用户。使用这种 "Windows 验证 "SQL Server 就可以利用 Windows NT/2000 的安全特性,例如安全验证和密码加密、审核、密码过期、最短密码长度,以及在多次登录请求无效后锁定帐号。
   原文地址 http://www.yesky.com/searchdatabase/504978202846822400/20050427/1942021.shtml
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页