最近尝试了一下SubVersion,觉得还不错,于是将现有项目的所有文件都添加到了版本库中。不过在对SQL Server的数据库文件进行版本控制时出现了一点小麻烦,大家都知道当SQL Server的数据库文件附加到数据库引擎上时是不能复制的,在这个时候SubVersion的客户端工具甚至不能检测到这些文件!于是在每次签入、签出的时候都要打开SQL Server Management Studio进行数据库的分离与附加,非常麻烦。
恰好SQL Server提供了一个命令行工具SQLCMD,于是我想能不能借助这个工具编写批处理文件,将数据库的分离和附加自动化呢?经过尝试之后发现这是可行的,下面介绍一下如何将此自动化。
首先说明一下我的项目目录的树形结构:
ArticleCenter是项目名称,在该文件夹下有一个Database子文件夹,里面只有mdf和ldf两个数据库文件。Attach.bat和Detach.bat分别是附加和分离数据库的批处理文件,直接双击这两个文件就可以执行相应的操作。
接下来看看如何使用SQLCMD,这个工具拥有很多的命令参数,但这里只使用了其中的几个:
sqlcmd -i <文件名>
-i参数后面跟一个sql文件的文件名,表示执行这个sql文件里的SQL语句。
sqlcmd -Q <SQL语句>
-Q参数后面跟一条SQL语句,表示执行该SQL语句。注意SQL语句要用双引号括起来,而且Q不能是小写。
另外,一般执行SQL语句之前都要连接和登录数据库引擎,这是通过-E,-S等参数指定的,如果省略这些参数,就是使用Window身份验证连接本地数据库引擎。关于SQLCMD就介绍到这里,如果对这个工具有兴趣的话,可以执行sqlcmd -?命令获取更多的帮助。
附加数据库的SQL语句如下:
USE [master]
GO
CREATE DATABASE [ArticleCenter_Database] ON
( FILENAME = N'E:\Zplutor\Documents\Projects\ArticleCenter\Database\ArticleCenter_Database.mdf' ),
( FILENAME = N'E:\Zplutor\Documents\Projects\ArticleCenter\Database\ArticleCenter_Database_log.ldf' )
FOR ATTACH
GO
这里有两条语句,而且比较长,我们可以先动态构造出这些语句,存放在文件中,然后通过sqlcmd -i命令来执行。下面就是Attach.bat文件的完整内容:
@echo off
ECHO USE [master] >> Create.sql
ECHO GO >> Create.sql
FOR %%I IN (*.mdf) DO ECHO CREATE DATABASE [%%~nI] ON >> Create.sql
FOR %%I IN (*.mdf) DO ECHO (FILENAME = N'%%~dpnxI'), >> Create.sql
FOR %%I IN (*.ldf) DO ECHO (FILENAME = N'%%~dpnxI') >> Create.sql
ECHO FOR ATTACH >> Create.sql
ECHO GO >> Create.sql
sqlcmd -i Create.sql
del Create.sql
ECHO.
PAUSE
为了让这个批处理更通用,不能将数据库名称和数据库文件路径硬编码到代码中,而是通过在运行时动态获取这些信息。对于批处理来说,FOR语句是最佳的选择。
FOR语句会遍历满足括号中条件的所有文件,将每个文件的完整文件名(这里的完整文件名指文件名加上扩展名)保存到指定的变量中(在这里这个变量就是%%I),然后执行DO后面的批处理语句。在这个语句中可以使用%%I标记,它将会被替换成完整文件名。
除了可以通过%%I来引用完整文件名之外,还可以通过以下的扩展标记来引用有关文件的更多信息:
%%~nI
该标记将被替换成文件名,不包括扩展名。
%%~xI
该标记将被替换成文件的扩展名。
%%~pI
该标记将被替换成文件的路径,该路径不包括驱动器盘符以及文件名。
%%~dI
该标记将被替换成文件所在驱动器的盘符。
以上标记可以任何搭配使用,例如%%~dpnxI将被替换成文件的完整路径。
第一条FOR语句对当前文件夹中的所有mdf文件执行DO后面的批处理语句,也就是将ECHO后面的内容输出到文件中,%%~nI将会被替换成文件名,不包含扩展名。第二条和第三条语句也是一样,其中%%~dpnxI将会被替换成文件的完整路经。
Attach.bat文件的内容就是如此简单,而Detach.bat就更简单了。分离数据库的SQL语句是:
EXEC master.dbo.sp_detach_db @dbname = N'ArticleCenter_Database', @keepfulltextindexfile=N'true'
由于只有一条语句,就不需要输出到文件中了,使用sqlcmd -Q命令即可。以下是Detach.bat文件中的内容:
@echo off
FOR %%I IN (*.mdf) DO sqlcmd -Q "EXEC master.dbo.sp_detach_db @dbname = N'%%~nI', @keepfulltextindexfile=N'true'"
ECHO.
PAUSE
希望本文对大家有所帮助。