Batch scripting for executing SQL scripts in a directory - sql

I want to develop a batch script which will execute each .sql SQL scripts present in the folder where the batch file is placed to and record the logs to a filename_sqloutput.txt file .
The condition is : If any script gives any error message like column name incorrect , or table name etc. The script execution should stop immediately and further scripts should not executed .
I tried with the below code: But its not working as even if the script is giving errors in the output file . The script execution is not stopping ..
Need your help !!!
#echo off
for /f %%a IN ('dir /b *.sql') do (call sqlcmd -S AMRVSP000000318 -i %%a -o"%%~na_sqloutput.txt"
findstr "Msg" %%~na_sqloutput.txt >nul & if %errorlevel% EQU 1 (exit) else (echo Successfully executed %%~na_sqloutput.txt)
)
pause

FINDSTR will set %ERRORLEVEL% as follows:
0 (False) a match is found in at least one line of at least one file.
1 (True) if a match is not found in any line of any file, (or if the file is not found at all).
2 Wrong syntax
An invalid switch will only print an error message in error stream.
Moreover, follow EnableDelayedExpansion article and rewrite the script to more readable structure:
#echo off
SETLOCAL EnableExtensions EnableDelayedExpansion
for /f %%a IN ('dir /b *.sql') do (
call sqlcmd -S AMRVSP000000318 -i %%a -o"%%~na_sqloutput.txt"
findstr "Msg" "%%~na_sqloutput.txt" 2>NUL
if !errorlevel! EQU 0 (
echo error occured %%~na_sqloutput.txt
rem pause to see error
pause
exit /B
) else (
echo Successfully executed %%~na_sqloutput.txt
)
)
pause

.... if errorlevel 1 (exit...
%errorlevel% is the initial value of errorlevel as it stands when the for is encountered.
See endless SO articles about using delayed expansion as another solution.
This syntax means "if the current errorlevel is 1 or greater dothis else dothat"

Related

Retry a sql query in case of failure in batch

This script processes all the sql files in a given folder and outputs the result to a csv. Do you have any ideas how could I adapt it to retry the sql file in case of error or failure?
#ECHO OFF
SET SQLCMD="C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE"
SET PATH="C:\Users\username\Desktop\Scripts\Reports\sql"
SET SERVER="localhost"
SET DB="database"
SET LOGIN="username"
SET PASSWORD="password"
SET OUTPUT="C:\Users\username\Desktop\Scripts\Reports\output_%date%-%time:~0,2%-%time:~3,2%-%time:~6,2%.csv"
CD %PATH%
ECHO %date% %time% > %OUTPUT%
for %%f in (*.sql) do (
%SQLCMD% -S %SERVER% -d %DB% -E -i %%~f >> %OUTPUT% -W -w 1024 -s";")
Thank you!
You cant test the ERRORLEVEL environment variable. typically a zero ERRORLEVEL value means success. also you need to enable delayed expansion to check it inside a block.
something like this may help,
SetLocal EnableDelayedExpansion
for %%f in (*.sql) do (
Set /a success=1
for /L %%w in (1,1,5) do ( rem retry five times
if !success! NEQ 0 (
%SQLCMD% -S %SERVER% -d %DB% -E -i %%~f >> %OUTPUT% -W -w 1024 -s";"
if !ERRORLEVEL! EQU 0 set /a success=0
)
)
if !success! NEQ 0 (
rem sql failed, log or advise
)
)
EndLocal
another important point, be careful with the PATH environment variable. you should better use another name as SQL_PATH or MY_PATH.
or you can use PUSHD & POPD to change your working dir
#echo off
SET ...
rem save current dir and jump to...
pushd "C:\Users\username\Desktop\Scripts\Reports\sql"
for %%f in (*.sql) do (
...
...
)
rem restore dir saved by pushd
popd

Batch file %%i was unexpected at this time

I am trying to get a patch file to set a variable to the number of instances that are running for a particular executable but am getting this error:
%%i was unexpected at this time
Here is my code:
for /f %%i in ('wmic process where name="chrome.exe" ^| find "chrome.exe" /c') do set var=%%i
I looked for an answer but none of the suggestions worked, even escaping the | with a ^.
If you are executing this directly in command prompt try this:
for /f %i in ('wmic process where "name='chrome.exe'" get caption /format:value ^| find "chrome.exe" /c') do set var=%i
for batch file left the double %

Populate a batch from a file

I have been trying to work this 1 out it's a fairly simple batch but I'm pretty much lost, the searches got my close but none seemed to work so I'm hoping somebody can help with this.
I have a batch file, it is far from optimized but basically what I am trying to do now is use the ping I have running in the batch which is written to check.csv should then populate the individual IP's at the beginning (hope that makes sense).
in a nut shell
The variables at the beginning should be populated from check.csv
Here is the code
'#echo off
rem set the individual IP addresses
Rem these are manually set at present, I want these set automatically from check.csv which is created at the end of this file at present but will be moved infront..
set sarah=10.1.14.106
set richard=10.1.15.135
set kathh=10.1.12.79
edited out a number of these to reduce the code on screen for you, but they are all the same format, name & IP
rem set the individual profile name
set n1=sharman
set n2=rburrell
removed more of the same (just duplicates the above code for a different user)
rem set the computer name
set sarahPC=PB7B237
set richardPC=PB1VAL9
removed more of the same
REM set the main install paths
set M3="C:\Users\dclare\Documents\VW Compiler\Installers\M3.exe"
set H3="C:\Users\dclare\Documents\VW Compiler\Installers\H3.exe"
set MooresInst="C:\Users\dclare\Documents\VW Compiler\Catalogues\PD PS\Catalogue"
Rem menu
#echo off
cls
:start
echo.
echo 1 Ping
echo 2 List
echo 3 DBase Installers
echo 4 EXE Installers
echo 5 End
echo.
#CHOICE /C:12345
if errorlevel 5 goto End
if errorlevel 4 goto EXEInstallers
if errorlevel 3 goto DBase
if errorlevel 2 goto List
if errorlevel 1 goto Ping
goto End
:End
Pause
Exit
:EXEInstallers
echo EXE Installers
echo.
echo Upload folder
Xcopy %M3% "S:\# All Public\Information Technology\CAD\VWorlds" /s /y /q
Xcopy %H3% "S:\# All Public\Information Technology\CAD\VWorlds" /s /y /q
echo.
echo %sarah%
Xcopy %M3% "\\%sarah%\c$\Users\%n1%\Desktop\" /s /y /q
Xcopy %H3% "\\%sarah%\c$\Users\%n1%\Desktop\" /s /y /q
echo.
echo %richard%
Xcopy %M3% "\\%richard%\c$\Users\%n2%\Desktop\" /s /y /q
Xcopy %H3% "\\%richard%\c$\Users\%n2%\Desktop\" /s /y /q
echo.
removed more of the same (just duplicates the above code for a different user)
goto Start
:DBase
echo Database Installers
echo.
echo %sarah%
Xcopy %MooresInst% "\\%sarah%\c$\Virtual Worlds\Catalogue" /s /y /q
echo.
echo %richard%
Xcopy %MooresInst% "\\%richard%\c$\Virtual Worlds\Catalogue" /s /y /q
echo.
removed more of the same (just duplicates the above code for a different user)
echo
Goto Start
:List
echo.
echo This is a list of the IP's used currently, check against any that fail.
echo.
echo Name Puter IP
echo sarah %sarahPC%%sarah%
echo richard %richardPC% %richard%
echo kathh %kathhPC% %kathh%
echo amarie %amariePC% %amarie%
removed more of the same (just duplicates the above code for a different user)
echo.
Pause
Goto Start
:Ping
#echo off
if exist "C:\Users\dclare\Documents\VW Compiler\Copy to Desktop\Results.csv" Del /s /q "C:\Users\dclare\Documents\VW Compiler\Copy to Desktop\Results.csv"
Echo Pinging list...
set ComputerList=list.txt
pause
Echo Computername,IP Address>Final.csv
setlocal enabledelayedexpansion
for /f "usebackq tokens=*" %%A in ("%ComputerList%") do (
for /f "tokens=3" %%B in ('ping -n 1 -l 1 %%A ^|findstr Reply ^|^| echo Not found Failed:') do (
set IPadd=%%B
echo %%A,!IPadd:~0, -1!>>Check.csv
))
pause
Goto Start'
here is the check.csv file contents
PB1VAL9 10.1.15.135
PB7B218 Failed
PB1VAL8 10.1.15.111
PB7B210 10.1.5.253
removed more of the same (just duplicates the above code for a different user)
Try this routine out to set your variables to ip addresses:
echo off
for /f "usebackq tokens=1,2" %%a in ("check.csv") (
echo setting %%a=%%b
set "%%a=%%b"
)
With this ping routine it shows if it is online or offline. I had to guess what you were trying to do as we don't have your files to test it.
Give us a sample of Check.csv if you want to populate a set of variables with the IP addresses inside it.
:Ping
#echo off
Del /s /q "C:\Users\dclare\Documents\VW Compiler\Copy to Desktop\Results.csv" 2>nul
Echo Pinging list...
set "ComputerList=list.txt"
pause
Echo Computername,IP Address>Final.csv
for /f "usebackq delims=" %%A in ("%ComputerList%") do (
ping -n 1 -l 1 %%A >nul
if not errorlevel 1 (
>>Check.csv echo %%A,online
) else (
>>Check.csv echo %%A,offline
)
)
pause
Goto Start

Batch Help -- Move File To Directory, If Exist Filename, Rename 001

I have a batch file that checks a root directory every 10 seconds for PDF files and copies those files to their corresponding subfolders of the exact same name.
What I'm missing is that I need my batch file to check the target subdirectory for the named file, and if the named file exists, to rename the new file to be copied to !filename!001.pdf and have the 001 get incremented as duplicate file names are copied. Here's what I got:
:loop
setlocal enabledelayedexpansion
cls
pushd c:\files\
for /f "tokens=*" %%1 in ('dir /a-d /b c:\files\*.pdf') do (
set filename=%%~n1&set dirname=!filename:~0,7!
dir c:\files /b *.pdf > location1list.tmp
for /f %%a in (location1list.tmp) do dir c:\files\%%a > location2list.tmp
if not exist c:\files\!dirname! (md c:\files\!dirname!)
move %%1 c:\files\!dirname!\>nul
)
timeout /t 10
goto:loop
Any suggestions how I can get the files renamed?
I.e. if Bob.pdf exists in the Bob folder and another Bob.pdf is added to the C:\files folder, I want it to be copied to the C:\files\bob folder as Bob001.pdf.
Something like this should do what you want. May need some tweaking. Also I have not tested it, just wrote it from memory. Need any explanations, just ask.
Script
#echo off
setlocal EnableExtensions EnableDelayedExpansion
pushd C:\files
:Main
for /f "tokens=*" %%A in ('dir /a-d /b *.pdf') do (
if not exist "%%~dpnA\*" md "%%~nA"
set "File=%%~dpnA\%%~nxA"
if exist "!File!" call :Name "!File!" File
echo !File!
move "%%~fA" "!File!"
)
goto Wait
:Name <Target> <Variable>
set "Count=0"
:Count
set /a "Count+=1"
set "Number=00%Count%"
if exist "%~dpn1%Number:~-3%%~x1" goto Count
set "%~2=%~dpn1%Number:~-3%%~x1"
goto :eof
:Wait
timeout /t 10
goto Main
:End
popd
endlocal
Limitations
Each target subdirectory can only handle a maximum of 1000 files as this is written. If the subdirectory hits this maximum then the script will get stuck in an infinite loop.
Update
Fixed an error in my initial script

Howto add a string to the 'type <filename>' DOS command before merging into file?

Question: I've several text files containing sql create table/column/view/storedProcedure textfiles. Now I want to merge the textfiles into one textfile.
I go into the directory, and type:
type *.sql >> allcommands.sql
Now to problem is I should add the text ' GO ' after every file's content.
I can append Go by doing
type *.sql >> allcommands.sql & echo GO >> allcommands.sql
But this only inserts go once.
How can I accomplish this with DOS commands ?
You want something like this:
for %%f in (*.sql) do type %%f >>allcommands.sql & echo GO >> allcommands.sql
The %% is for use in a batch file. If you're not running it from a batch file you only need single % signs.
Try this one
for %%f in (*.sql) do (
type %%f >>allcommands.sql
echo. >> allcommands.sql
echo GO >> allcommands.sql
echo. >> allcommands.sql )
it adds newline then go for each SQL file. it works for me try it.
Use copy to concatenate the first file with a file with "GO" text, then concatenate again with the second file.
#echo off
CLS
::concat.bat outfile.sql
setlocal EnableDelayedExpansion
If EXIST GOTMP.TMP DEL /Q GOTMP.TMP
Echo GO>GOTMP.TMP
ECHO.>>GOTMP.TMP
If EXIST "%~1" DEL /Q "%~1"
Echo.>"%~1"
for /f "tokens=*" %%A in ('dir /a-d /on /b "*.sql"') do call :perfaction "%%A%" "%~1"
ECHO Done Generating Output "%~1"
ECHO.
pause
Goto :EOF
:perfaction
ECHO "%~1"
copy "%~2"+"%~1"+GOTMP.TMP "%~2"
GOTO :EOF