用批处理写的自动生成tablediff脚本的工具

工具的作用:通过交互式提问生成tablediff的执行命令,而且将命令执行后生成的同步数据脚本和日志放在指定的目录中。
工具的好处:可以将要通过tablediff比较的表放到广本文件tables.txt中。该批处理会遍历该文件中的每一行。会将每张表tablediff执行后生成和表名和目的机器名对就的.sql文件。要执行时,直接根据文件名就可以看出在什么订阅的机器上执行。
 
使用注意:每次执行前,需要编辑tables.txt文件,将要进行tablediff校验的表名放到该文件中,同时需要删除tabcomp.bat文件,该文件会在交互式提问后生成最新的。当交互式操作完成后,执行tabcomp.bat命令就可以在指定的目录中生成tablediff的结果了。
 
批处理代码如下:


@echo off
if not exist tables.txt (goto end)

:sourceserver
set sourceserver=
set /p  sourceserver=请输入源机器名字
if "%sourceserver%" == "" goto sourceserver

:sourcedatabase
set sourcedatabase=
set /p  sourcedatabase=请输入源数据库名字
if "%sourcedatabase%" == "" goto sourcedatabase

:sourceschema
set sourceschema=
set /p  sourceschema=请输入源架构名
if "%sourceschema%" == "" goto sourceschema

:sourceuser
set sourceuser=
set /p  sourceuser=请输入源用户名
if "%sourceuser%" == "" goto sourceuser

:sourcepassword
set sourcepassword=
set /p  sourcepassword=请输入源用户密码
if "%sourcepassword%" == "" goto sourcepassword

:destinationserver
set destinationserver=
set /p  destinationserver=请输入目的机器名字
if "%destinationserver%" == "" goto destinationserver

:destinationdatabase
set destinationdatabase=
set /p  destinationdatabase=请输入目的数据库名字
if "%destinationdatabase%" == "" goto destinationdatabase

:destinationschema
set destinationschema=
set /p  destinationschema=请输入目的架构名
if "%destinationschema%" == "" goto destinationschema

:destinationuser
set destinationuser=
set /p  destinationuser=请输入目的用户名
if "%destinationuser%" == "" goto destinationuser

:destinationpassword
set destinationpassword=
set /p  destinationpassword=请输入目的用户密码
if "%destinationpassword%" == "" goto destinationpassword

:datapath
set datapath=
set /p  datapath=请输入保存生成文件的路径(默认为当前目录):

for /F %%i in (tables.txt) do @echo tablediff /sourceserver"%sourceserver%" /sourcedatabase"%sourcedatabase%" /sourceschema"%sourceschema%" /sourcetable"%%i" /sourceuser"%sourceuser%" /sourcepassword"%sourcepassword%" /destinationserver"%destinationserver%" /destinationdatabase"%destinationdatabase%" /destinationschema"%destinationschema%" /destinationtable"%%i" /destinationuser"%destinationuser%" /destinationpassword"%destinationpassword%" /f"%datapath%.\syn%%i-%destinationserver%.sql" /o"%datapath%.\output-%%i-%destinationserver%.txt">>tabcompc.bat
rem echo copy syn*%destinationserver%.sql syn%destinationserver%-Z.SQL>>tabcomp.bat
rem echo sqlcmd -S%destinationserver%  -U%destinationuser%  -P%destinationpassword%   -d %destinationdatabase% -f i:65001  -i syn%destinationserver%-Z.SQL   -o execsyn%destinationserver%.log>>tabcomp.bat
echo for %%%%f in (*.sql) do  sqlcmd -S %destinationserver%  -U %destinationuser%  -P %destinationpassword%   -d %destinationdatabase% -f i:65001  -i %%%%f  -o execsyn%%%%f.log>>tabcompc.bat
set sourceserver=
set sourcedatabase=
set sourceschema=
set sourcetable=
set sourcelocked=
set sourceuser=
set sourcepassword=
set destinationdatabase=
set destinationlocked=
set destinationpassword=
set destinationschema=
set destinationserver=
set destinationtable=
set destinationuser=
set datapath=
:end
echo tables.txt文件不存在请手工生成该文件

以上的批处理中有两行注释掉了,这两行的功能是分别将TABLEDIFF生成的SQL文件使用SQLCMD命令行到目的机器上去执行,只使用一行就行,这两行的差异在于将生成的多个SQL文件是分别执行还是合并在一起执行,如果合并在一起执行的话,SQL文件就会很大,但SQLCMD这个工具对大的SQL文件执行会报“内存不足”的错误,咨询过微软也没有好的解决方案,只能算是这个EXE的特点了。

 

但如果是在SQL2000的环境通过TABLEDIFF进行比差异,需要有Frame work的支持,而且SQL2000中没有SQLCMD功能,原来的ISQL和OSQL也不支持代码页的转换不向SQLCMD中有-f参数,这样对于我们做批处理就是一个小障碍。所以对于纯SQL2000的环境中要使用TABLEDIFF进行差异比对和差异数据的执行,必须要通过写字板手工转换差异SQL文件,如果要写批处理,则必须找一个命令行的UTF-8转换为UNICODE代码的工具,在网上找了一个强人写的一个VBS,试过后很爽。所以在此推荐给大家,代码如下:

' *==============================================================================*
' * CMD 命令行编码转换工具包括GB2312,UTF-8,Unicode,BIG5...支持拖拽、文件另保存为 *
' * CodeChange.vbs     BY: yongfa365
' * GB2Ue.vbs          BY: fastslz
' *==============================================================================*
aCode = "GB2312"
bCode = "Unicode"
Show = "本脚本仅支持"&aCode&"到"&bCode&"的转换,请拖拽单个要转换的文件到此文件上!    "
Usage1 = "语法1:GB2Ue.vbs [驱动器][目录][文件名] (直接替换原文件模式)"
Usage2 = "语法2:GB2Ue.vbs [驱动器][目录][文件名]  [目标驱动器][目录][新名称] /Y"
Usage3 = "        如果目标新文件已存在,使用/Y参数后将直接替换而不提示是否改写!  "
Usage4 = "命令行编码转换工具 BY: fastslz"

Set objArgs=WScript.Arguments
Set fso=CreateObject("Scripting.FileSystemObject")
if objArgs.Count=0 Then
   MsgBox Show &vbCrLf&vbCrLf& Usage1 &vbCrLf& Usage2 &vbCrLf& Usage3, vbInformation, Usage4
   Wscript.Quit
end if
if not objArgs.Count < 3 Then
       Options="/y"
       ignoring = StrComp(objArgs(2), Options, vbTextCompare)
       if ignoring = 0 Then
          Sourcefile=objArgs(0)
          Getfile=objArgs(1)
          else
          MsgBox "文件数量或参数太多,拖拽批量处理请用 ANSI2Unicode.vbs     ", vbInformation, "程序意外终止"
          Wscript.Quit
       end if
       else
       if not objArgs.Count < 2 Then
          Sourcefile=objArgs(0)
          Getfile=objArgs(1)
          if fso.FileExists(objArgs(1)) then
             Choice = MsgBox ("待处理文件“"+Sourcefile+"” ==> 目标文件“"+Getfile+"”    "&vbCrLf&"目标文件已存在,是否改写现有文件?“"+objArgs(1)+"”    ",vbQuestion+vbYesNo,"是否改写")
             if Choice = vbYes Then
                Getfile=objArgs(1)
                else
                Wscript.Quit
             end if
          end if
          else
          Sourcefile=objArgs(0)
          Getfile=objArgs(0)
       end if
end if

Call CheckCode (Sourcefile)
Call WriteToFile(Getfile, ReadFile(Sourcefile, aCode), bCode)
Wscript.Quit

Function ReadFile (Sourcefile, CharSet)
    Dim Str
    Set stm = CreateObject("Adodb.Stream")
    stm.Type = 2
    stm.mode = 3
    stm.charset = CharSet
    stm.Open
    stm.loadfromfile Sourcefile
    Str = stm.readtext
    stm.Close
    Set stm = Nothing
    ReadFile = Str
End Function

Function WriteToFile (Getfile, Str, CharSet)
    Set stm = CreateObject("Adodb.Stream")
    stm.Type = 2
    stm.mode = 3
    stm.charset = CharSet
    stm.Open
    stm.WriteText Str
    stm.SaveToFile Getfile,2
    stm.flush
    stm.Close
    Set stm = Nothing
End Function

Function CheckCode (Sourcefile)
    Dim slz
    set slz = CreateObject("Adodb.Stream")
    slz.Type = 1
    slz.Mode = 3
    slz.Open
    slz.Position = 0
    slz.Loadfromfile Sourcefile
    Bin=slz.read(2)
    if AscB(MidB(Bin,1,1))=&HEF and AscB(MidB(Bin,2,1))=&HBB Then
       Codes="UTF-8"
       elseif AscB(MidB(Bin,1,1))=&HFF and AscB(MidB(Bin,2,1))=&HFE Then
              Codes="Unicode"
              else
              Codes="GB2312"
    end if
    if not aCode = Codes Then
           MsgBox "待处理文件 “"&Sourcefile&"”"&vbCrLf&"该文件原始编码不是"&aCode&",本脚本仅支持"&aCode&"到"&bCode&"的转换!    ",vbInformation,"错误终止"
           WScript.Quit
    end if
    slz.Close
    set slz = Nothing
End Function


需要注意的是:

1.通过TABLEDIFF生成的差异SQL文件是UTF-8格式的,但这种格式还不完全是标准的UTF-8,我经过分析发现这种格式是UTF-8的文件头,而内容却是GB2313的,如果通过以上脚本来直接换会发现脚本报错,说此文件不是UTF-8的文件,所以,要强制转换,还需要把以上代码中的

    if not aCode = Codes Then
           MsgBox "待处理文件 “"&Sourcefile&"”"&vbCrLf&"该文件原始编码不是"&aCode&",本脚本仅支持"&aCode&"到"&bCode&"的转换!    ",vbInformation,"错误终止"
           WScript.Quit
    end if

给注释掉,让他不检测文件版本,直接给按UTF-8给转换掉,这样才能通过OSQL等2000下的工具正确的执行。

2.如果把这种通过TABLEDIFF生成的差异SQL文件通过SQLCMD来执行就会出现很多码,幸好SQLCMD中有一个参数-f 通过-f i:65001这个参数就可以解决UTF-8差异数据文件执行的问题。

3.还有一点,就是SQL2005中的TABLEDIFF和SQL2008中的TABLEDIFF有差别,使用SQL2008版的TABLEDIFF不但性能差,而且生成的差异文件执行会报错,我发现的问题是对于NULL值,SQL2008版本中生成的脚本是N‘NULL’,而SQL2005中的TABLEDIFF中则生成的是NULL,所以推荐大家使用SQL2005中的TABLEDIFF文件。至于SQL2008中的TABLEDIFF会不会比SQL2005中的功能多,这点偶还没有发现,希望会有进步,但至少目前是发现了其不足。

4.最近验证了sqlserver2008r2中的tablediff工具,和sqlserver2008一样有问题,所以不得不使用sql2005中带的tablediff.exe

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值