Windows批处理SQL Server脚本 - 打破子程序

时间:2014-06-19 15:23:47

标签: sql sql-server windows batch-file

我已经编写了一个批处理脚本,并考虑了几个意图:

  • 生成特定于环境的整理DDL脚本
  • 支持通过SQL Server的sqlcmd可执行文件
  • 执行整理的脚本

脚本如下:

::
:: mydb-load-v1.bat
:: 
:: Script for dropping and re-creating version 1 of the MyDB database DDL
::
ECHO off
CLS
ECHO( 
ECHO #####################################################################
ECHO # MyDB Version 1 Load Script      
ECHO #
ECHO # Started at %DATE% %TIME%              
ECHO #
ECHO # Script format is: 
ECHO # mydb-load-v1.bat 
ECHO #
ECHO #####################################################################
ECHO(

:: Initialize script variables
SET "DDL_DIR=%CD%\ddl"
SET "DDL_TEMP_FILE=mydb-v1-ddl.final.sql.tmp"
SET "DDL_FILE=mydb-v1-ddl.final.sql"
SET "SCRIPT_ENVIRONMENT="
SET "SCRIPT_SERVER="
SET "SCRIPT_DATABASE="
SET "SCRIPT_RESULT_LOG=load-ddl-results.log"
SET "DB_USERNAME="
SET "DB_PASSWORD="
SET "SCRIPT_EXECUTE="

:: Which environment are we using? 
SET /P "SCRIPT_ENVIRONMENT=Please enter the environment (0=Local, 1=Dev, 2=QA, 3=UAT, 4=Prod):"

IF %SCRIPT_ENVIRONMENT%==0 (
    SET SCRIPT_SERVER=myserver\SQLEXPRESS
    SET SCRIPT_DATABASE=MyDBDev
)
IF %SCRIPT_ENVIRONMENT%==1 (
    SET SCRIPT_SERVER=devserver
    SET SCRIPT_DATABASE=MyDBDev
)
IF %SCRIPT_ENVIRONMENT%==2 (
    SET SCRIPT_SERVER=qaserver
    SET SCRIPT_DATABASE=MyDBQA
)
IF %SCRIPT_ENVIRONMENT%==3 (
    SET SCRIPT_SERVER=uatserver
    SET SCRIPT_DATABASE=MyDBUAT
)
IF %SCRIPT_ENVIRONMENT%==4 (
    SET SCRIPT_SERVER=prodserver
    SET SCRIPT_DATABASE=MyDBPROD
)

:: Checks if the ddl file exists, deletes it if so and then creates a new blank one
ECHO(
ECHO Generating the %DDL_FILE% file
ECHO(
IF exist %DDL_TEMP_FILE% (
    del %DDL_TEMP_FILE%
)
IF exist %DDL_FILE% (
    del %DDL_FILE%
)
copy NUL %DDL_TEMP_FILE%

IF exist %SCRIPT_RESULT_LOG% (
    del %SCRIPT_RESULT_LOG%
)

:: Write out the DDL initialization
ECHO USE [%SCRIPT_DATABASE%] >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
ECHO GO >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%

:: Append the individual drop scripts to the new script file
TYPE %DDL_DIR%\drop-dbo-tEmailLastScan.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
TYPE %DDL_DIR%\drop-dbo-userExternalSysLogin.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
TYPE %DDL_DIR%\drop-dbo-userPasswordHistory.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
TYPE %DDL_DIR%\drop-dbo-userProfile.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
TYPE %DDL_DIR%\drop-dbo-userLogin.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
ECHO GO >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%

:: Append the individual create scripts to the new script file
TYPE %DDL_DIR%\create-dbo-userLogin.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
ECHO GO >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
TYPE %DDL_DIR%\create-dbo-tEmailLastScan.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
ECHO GO >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
TYPE %DDL_DIR%\create-dbo-userExternalSysLogin.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
ECHO GO >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
TYPE %DDL_DIR%\create-dbo-userPasswordHistory.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
ECHO GO >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
TYPE %DDL_DIR%\create-dbo-userProfile.sql >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%
ECHO GO >> %DDL_TEMP_FILE%
ECHO( >> %DDL_TEMP_FILE%

REN %DDL_TEMP_FILE% %DDL_FILE%

SET /P "SCRIPT_EXECUTE=Would you like to run the script now (0=No, 1=Yes):"

IF [%SCRIPT_EXECUTE%]=="1" (
    ECHO(
    ECHO Running sqlcmd.exe
    ECHO(
    :: Check that the command sqlcmd.exe is on the path.
    for %%X in (sqlcmd.exe) do (SET FOUND_SQLCMD=%%~$PATH:X)
    IF not defined FOUND_SQLCMD (
        ECHO Script failed, unable to find sqlcmd.exe on the path
        ECHO Make sure sqlcmd.exe is available on the path to run this script
        ECHO Exiting the script
        exit /B 500
    )

    SET /P "DB_USERNAME=Enter the database user name:"
    SET /P "DB_PASSWORD=Enter the database user name:"

    :: Call the sqlcmd executable
    call sqlcmd.exe -S %SCRIPT_SERVER% -U %DB_USERNAME% -P %DB_PASSWORD% -i %DDL_FILE% -o %SCRIPT_RESULT_LOG%   

    ECHO(
    ECHO Call to sqlcmd.exe is complete. Please check the log file for the ddl
    ECHO(
) 

ECHO(
ECHO #########################################
ECHO # 
ECHO # Completed at %DATE% %TIME%
ECHO # 
ECHO #########################################
ECHO( 
EXIT /B 0

我的问题是,如何将其分解为子程序,以便脚本在多次迭代中成功运行?当我试图分解以下部分之间的部分时:

IF [%SCRIPT_EXECUTE%] ==" 1" (   GOTO MySubroutine )

我发现子程序永远不会被调用。

同样,我注意到在全局脚本级别设置的变量的不一致性,这些变量稍后在子程序中调用;具体来说,它们是空的。如您所见,我在脚本开始时初始化所有变量,希望不会出现此问题。

欢迎您的反馈,感谢您抽出宝贵时间。

1 个答案:

答案 0 :(得分:0)

通过更好地了解Windows批处理文件如何扩展变量值,我决定将IF [%SCRIPT_EXECUTE%] ==“1”下的内容拉到一个单独的常用批处理文件中,然后只需要一个调用这比试图绕过我看到的在代码块中使变量值更正的黑客更简单。另外,根据sachadee,我添加了额外的括号。