2. 外部命令与文件操作
(1)外壳命令xp_cmdshell
使用xp_cmdshell, 我们可以像执行DOS命令那样采用命令行方式来执行外部命令,包括象dir、mkdir和copy之类的系统命令,也能够执行普通的exe命令。通过xp_cmdshell执行命令的权限和运行SQL Server服务的用户权限一样大。通过xp_cmdshell, 我们一下就把数据库的功能进行了极大的延展,由于command命令的灵活性,我们可以用它来创建目录,拷贝,压缩文件,甚至调用自己写的一些控制台程序或者脚本。
注意:这里使用SQL2005的用户需要注意,出于安全的考虑,SQL2005安装以后默认并不启用xp_cmdshell,也就是说它默认是被禁制使用的。但是我们可以通过如下方法打开启用这个功能强大又危险的存储过程:
从菜单所有程序, 通过点击”Microsoft SQL Server 2005 => Configuration Tools(配置工具) => SQL Server Surface Area Configuration(外围配置管理器)”, 打开Surface Area Configuration 的管理程序,点击”Surface Area Configuration for features”, 将xp_cmdshell的选激活即可。
定义
示例
显示当前文件夹的的文本文件。
存储过程会将命令的文字输出通过多行记录集的方式进行返回,如下。EXEC master..xp_cmdshell 'dir c:\*.txt'
驱动器 C 中的卷是 SYSTEM
卷的序列号是 0482-xxxx
NULL
c:\ 的目录
NULL
2006-08-05 20:32 13,649 cmd.txt
2006-08-05 20:32 4 response.txt
2004-06-25 09:31 97,355 debug.txt
….
2005-12-03 19:26 27,005 cdnlog.txt
9 个文件 147,173 字节
0 个目录 3,316,301,824 可用字节
NULL
当然,我们还可以用它做更多的事情,如下代码演示了一个利用net命令来关闭SQL Server服务的过程,它向域中的SQL用户发送通知消息,并且暂停和停止数据库。
(2)文件访问xp_fileexistCREATE PROC shutdownSQLServer
AS
EXEC xp_cmdshell 'net send /domain:SQL_USERS ''SQL Server
shutting down in 10 minutes. No more connections
allowed.', no_output
EXEC xp_cmdshell 'net pause sqlserver'
WAITFOR DELAY '00:05:00'
EXEC xp_cmdshell 'net send /domain: SQL_USERS ''SQL Server
shutting down in 5 minutes.', no_output
WAITFOR DELAY '00:04:00'
EXEC xp_cmdshell 'net send /domain:SQL_USERS ''SQL Server
shutting down in 1 minute. Log off now.', no_output
WAITFOR DELAY '00:01:00'
EXEC xp_cmdshell 'net stop sqlserver', no_output
文件访问的相关存储过程众多,比如xp_fileexist, xp_create_subdir, xp_delete_file, xp_delete_file等等。由于xp_cmdshell可以执行一些文件相关的创建,删除的操作,这里主要对xp_fileexist进行详述。
xp_fileexist是用来检查文件或者文件夹是否存在的,显然分析由xp_fileexist返回的结果比分析由执行Exec xp_cmdshell ‘dir filename’返回的文本信息来得轻松并且可靠得多。Xp_fileexist支持两种方式返回结果,一个是通过输出参数@File_Exists OUT来返回结果,另外一种方式就是不指定输出参数,那么它将返回一个有三列结果集, 分别代表文件是否存在 文件是一个存在的目录,父目录是否已存在。
? 定义
示例
这里的"C:\bt"是一个存在的目录,我们来看看执行后会有什么结果。
返回的结果是0, 1, 1。这表示"C:\bt"是一个存在的目录,并且父目录也存在。exec xp_fileexist 'C:\bt\'
这里的"C:\test.txt"是一个普通文件,我们再来看看执行这句脚本有什么结果。
返回的结果是1, 0, 1。这表示"C:\test.txt"是一个存在的文件,并且父目录也存在。exec xp_fileexist 'c:\test.txt
当然我们也可以通过output参数的方式来获取结果,让我们看看下面的脚本运行会有什么结果。
结果是:declare @File_Exists int
exec xp_fileexist 'C:\bt\', @File_Exists OUT
print @File_Exists
exec xp_fileexist 'c:\test.txt', @File_Exists OUT
print @File_Exists
我们发现通过output参数,只能够检查文件是否存在,并不能检查目录是否存在,所以具体使用哪种输出方式,要根据你的需要而定。(1 行受影响)
0
(1 行受影响)
1
EXEC master..xp_cmdshell 'dir c:\*.txt'