windows batch file executing sql server query - sql-server

I have a batch file that should execute a sql server query and check if count = 0 or more. if 0 exit if not I run another .exe program.
When I run this, the if statement "if ct EQU 0" is not working correctly. In my table count is zero.
#ECHO OFF
SET Header=-----------------------------------------------------
set ct=-1
sqlcmd -S OURDATA\DEVINSTANCE -E -q "SELECT ct=count(*) FROM [dbo].[Table] where Name like '%AMY%' and status=1"
if ct EQU 0 (
echo no count)
goto end
)
if ct GRT 0 (
start "" "C:\test.exe"
if %ERRORLEVEL% NEQ 0 (
echo %header%
Echo There has been an error.
pause
goto end)
)
:end
echo %header%
echo END
Thanks
R

Try replacing it with something like this:
for /F usebackq %%i in (`sqlcmd -E -S OURDATA\DEVINSTANCE -h-1 -Q "SELECT count(*) FROM [dbo].[Table] where Name like '%AMY%' and status=1"`) do (
set count=%%i
)
Hope this helps you.

Related

SQLCMD with 1 return value

I am trying to return a single value from a sqlcmd query used in a bat file.
It seems that i have some errors with the syntax used in my sqlcmd query. I am very new to coding in cmd, any guidance would help. I am using this query on a server.
#ECHO off
echo _________________________________________________________
Echo The following inputs are required:
Echo [1] Database Server Name
Echo [2] Configuration Type
echo ---------------------------------------------------------
CD %~dp0
SET /p DBSERVER="Enter [1]: "
SET /p CFIGTYPE="Enter [2]: "
echo Deploying...
ECHO %CFIGTYPE%
::-----------------------------------------------TEST1----------------------------------------
IF (%CFIGTYPE% == 'TEST1' ){
for /f %%a in ('sqlcmd -S %DBServer% -v DBServer="%DBServer%" -Q "SET NOCOUNT ON; select ConfigValue FROM SERVICE.dbo.configuration WHERE ConfigOption = 'TEST1' "')
do set ColumnVar=%%a
echo %ColumnVar%
CMD \K
IF (%ColumnVar% == 'Y'){
Echo WOHOOOO
cmd /k
}
Else{
ECHO NOOOOOO
CMD /K
}
My code just closes after it reaches the sqlcmd portion.
Revised code in light of comments:
(does not solve problem)
#ECHO off
echo _________________________________________________________
Echo The following inputs are required:
Echo [1] Database Server Name
Echo [2] Configuration Type
echo ---------------------------------------------------------
SET /p DBSERVER="Enter [1]: "
SET /p CFIGTYPE="Enter [2]: "
echo Deploying...
ECHO %CFIGTYPE%
::-----------------------------------------------TEST1----------------------------------------
IF "%CFIGTYPE%"=="TEST1" (
for /f %%a in ('sqlcmd -S %DBServer% -v DBServer="%DBServer%" -Q "SET NOCOUNT ON; select ConfigValue FROM SERVICE.dbo.configuration WHERE ConfigOption = 'TEST1' "')
do set ColumnVar=%%a
echo %ColumnVar%
IF "%ColumnVar%"=="Y" (
Echo WOHOOOO
cmd /k
)
Else (
ECHO NOOOOOO
CMD /K
)
)
New revision:
#ECHO off
echo _________________________________________________________
Echo The following inputs are required:
Echo [1] Database Server Name
Echo [2] Configuration Type
echo ---------------------------------------------------------
SET /p DBSERVER="Enter [1]: "
SET /p CFIGTYPE="Enter [2]: "
echo Deploying...
ECHO %CFIGTYPE%
::-----------------------------------------------TEST1----------------------------------------
IF "%CFIGTYPE%"=="TEST1" (
for /f %%a in ('sqlcmd -S %DBServer% -v DBServer="%DBServer%" -Q "SET NOCOUNT ON; select ConfigValue FROM SERVICE.dbo.configuration WHERE ConfigOption = 'TEST1' "')
IF "%%a"=="Y" (
Echo WOHOOOO
PAUSE
) Else (
ECHO NOOOOOO
PAUSE
)
)
I didnt manage to find a solution that allows me to set a value to a variable from a sql query. Instead, i have output the results to a file and read the results from there and then delete the file. Here goes the code:
#ECHO off
echo _________________________________________________________
Echo The following inputs are required:
Echo [1] Myserver
echo ---------------------------------------------------------
CD %~dp0
SET /p DBSERVER="Enter [1]: "
:: Get Configuration Type
sqlcmd -S %DBServer% -E -i test.sql -b -v TYPE="CFIGTYPE" -h -1 >result.txt
set /p CFIGTYPE=<result.txt
call :Trimspaces CFIGTYPE %CFIGTYPE%
del "result.txt"
:: ------------------------------------------------ FUNCTIONS--------------------------------------------------------------------------------------------------------------
:trimSpaces2 retval string -- trims spaces around string and assigns result to variable
:: -- retvar [out] variable name to store the result in
:: -- string [in] string to trim, must not be in quotes
for /f "tokens=1*" %%A in ("%*") do set "%%A=%%B"
EXIT /b
:trimSpaces varref -- trims spaces around string variable
:: -- varref [in,out] - variable to be trimmed
call call:trimSpaces2 %~1 %%%~1%%
EXIT /b
Since the output file would contain empty i have included a function taken from
https://www.dostips.com/DtTipsStringOperations.php
That would eliminate the empty spaces when reading the file.
I have an extra test.sql which contains the following code:
SET NOCOUNT ON;
select configvalue FROM Service.dbo.Configuration WHERE ConfigOption = '$(type)'

What am I doing wrong in this batch file?

When I run the below batch file code, it thinks that the server address is 'dbuser' and the Database is 'False'
What am I doing wrong?
Here is the code:
#echo off
set toolspath=C:\Program Files (x86)\Folder\Application
Set ApplicationServer=00.0.00.000
Set ApplicationDatabase=dbApplication
Set ApplicationUser=dbuser
Set ApplicationPassword=abcdefg
Set ApplicationUpgradeFromPre12_5=False
REM echo "Attaching dbApplication .. "
REM osql -S %ApplicationServer% -U %ApplicationUser% -P %ApplicationPassword% -i %ApplicationScriptsPath%\AttachApplicationDatabase.sql
REM osql -S %ApplicationServer% -U %ApplicationUser% -P %ApplicationPassword% -i %ApplicationScriptsPath%\SetDBVersion.sql
REM echo "Done."
call ApplicationUpgradeScripts.bat %%2 %ApplicationUser% %ApplicationPassword% %ApplicationDatabase% %ApplicationUpgradeFromPre12_5%
#if ERRORLEVEL 1 goto ERRORSEXIT
#Echo %ApplicationDatabase% Database Updated Successfully.
goto FINISH
:ERRORSEXIT
#Echo Error: Database Excecuted With Error. To Find out Exact Error see file ErrorLog.log
exit /B 1
goto ENDBUILD
:FINISH
#Echo All Databases Excecuted Successfully.
exit 0
:ENDBUILD
pause

Batch script check array variable always goes to ELSE statement

I have a batch script which asks the user to input a server. Then it checks if it is from an array, where the servers require 3 password to login. Otherwise 2 passwords are needed. I check this in a for loop but always end up going to the else statement. Why? Here is the code:
#echo off
set arrayserver[0]=server1
set arrayserver[1]=server2
set arrayserver[2]=server3
set arrayserver[3]=server4
set arrayserver[4]=server5
set arrayserver[5]=server6
set arrayserver[6]=server7
set arrayserver[7]=server8
set arrayserver[8]=server9
set arrayserver[9]=server10
set arrayserver[10]=server11
set arrayserver[11]=server12
set arrayserver[12]=server13
set arrayserver[13]=server14
set arrayserver[14]=server15
set arrayserver[15]=server16
set arrayserver[16]=server17
set arrayserver[17]=server18
set arrayserver[18]=server19
set arrayserver[19]=server20
set arrayserver[20]=server21
set arrayserver[21]=server22
set arrayserver[22]=server23
set arrayserver[23]=server24
set arrayserver[24]=server25
set arrayserver[25]=server26
set arrayserver[26]=server27
set user2=user2
set user3=user3
set i=0
set /p server=Enter server:
for /F "tokens=2 delims==" %%s in ('set arrayserver[') do (
if "%server%" == "%%s" (
goto breakit
) else (
goto breakit2
))
:breakit
echo You will be prompted for 3 passwords:
echo -pass1
echo -pass2
echo -Oracle user
echo ssh -t -A %user2%#hop2 ssh -t -A %EDSUSER%#%server% su - oracle > C:\Temp\linkche.txt
"C:\Program Files (x86)\Putty\putty.exe" -ssh -A -t %USER%#hop1 -m C:\Temp\linkche.txt
del C:\Temp\linkche.txt
goto :oef
:breakit2
echo You will be prompted for 2 passwords:
echo -pass1
echo -Oracle user
echo ssh -t -A %user2%#hop2 ssh -A oracle#%server% > C:\Temp\linkche.txt
"C:\Program Files (x86)\Putty\putty.exe" -ssh -A -t %USER%#hop1 -m C:\Temp\linkche.txt
del C:\Temp\linkche.txt
goto :oef
Well, that's simple. You are in a loop but after checking the first server you are entering the ELSE case. So you are jumping out of the loop after the first iteration. You can verify this by entering server1. In this case the IF case is executed. Further, GOTO :oef makes no sense. I suppose you want to do GOTO :EOF. While EOF means EndOfFile, OEF means nothing (or possibly OfEndFile? :D).
To fix your problem you should modify your loop like this:
...
for /F "tokens=2 delims==" %%s in ('set arrayserver[') do (
if "%server%" == "%%s" (
goto breakit
)
)
goto breakit2
...
Now you will jump to breakit if the input is between server1 and server27 or to breakit2 otherwise. And don't forget to replace oef with eof.
You do not need to iterate over the array elements. If you define the array with the server values as subscripts with any value in the element (instead of numeric subscripts with the server in the value), then you may directly test if such server exist via a if defined arrayserver[%server%] ... command. I also use a simpler way to define the array.
#echo off
rem Define the server array with the server *in the subscript*; the assigned value does NOT matter
for %%a in (server1 server2 server3 server4 server5 server6 server7 server8 server9 server10
server11 server12 server13 server14 server15 server16 server17 server18 server19 server20
server21 server22 server23 server24 server25 server26 server27) do (
set arrayserver[%%a]=3
)
set user2=user2
set user3=user3
set /p server=Enter server:
if not defined arrayserver[%server%] goto passwords-2
:passwords-3
echo You will be prompted for 3 passwords:
echo -pass1
echo -pass2
echo -Oracle user
echo ssh -t -A %user2%#hop2 ssh -t -A %EDSUSER%#%server% su - oracle > C:\Temp\linkche.txt
"C:\Program Files (x86)\Putty\putty.exe" -ssh -A -t %USER%#hop1 -m C:\Temp\linkche.txt
del C:\Temp\linkche.txt
goto :eof
:passwords-2
echo You will be prompted for 2 passwords:
echo -pass1
echo -Oracle user
echo ssh -t -A %user2%#hop2 ssh -A oracle#%server% > C:\Temp\linkche.txt
"C:\Program Files (x86)\Putty\putty.exe" -ssh -A -t %USER%#hop1 -m C:\Temp\linkche.txt
del C:\Temp\linkche.txt
goto :eof
You may even define array elements with different values for 2 and 3 passwords, and then directly use their values to go to the appropriate section with no if command!
setlocal EnableDelayedExpansion
rem Servers with 3 passwords:
for %%a in (server1 server2 server27) do set arrayserver[%%a]=3
rem Servers with 2 passwords:
for %%a in (serverA serverB serverZ) do set arrayserver[%%a]=2
set /p server=Enter server:
goto passwords-!arrayserver[%server%]!
For further info about array management in Batch files, see this post.

Sftp Batch script on Windows OS to detect success/failure

How do I run sftp Batch script on Windows OS to detect success/failure?
I use %errorlevel% to detect success/failure, but the %errorlevel% can be returned by 0 despite the session is failed and the file is not uploaded to the server.
My script is below:
sftp2 -D4 -B ftp.txt %dest%
set result=%errorlevel%
if result EQU 0 (
echo successful
) else (
echo unsuccessful
)
exit %result%
Content of ftp.txt
put ABC.TXT
QUIT
You need to change
if result EQU 0 (
to
if %result% EQU 0 (

Streamlining a batch file calling a sql file

We currently have a scheduler to run audits. This scheduler will call a batch file with a parameter, and the batch file calls a sql script (based on the parameter), which in turn calls a stored proc.
For each audit that runs, a separate batch file, and sql file. Best case I'd like to combine the two below files into 1 file that can be used for every new audit. Worst case I'd at least like to combine to get 1 file for each audit instead of two. Hopefully you all can help?
Batch File
#echo on
Echo Running SQL Command File for '%1' Data Audit Check
del "D:\Internal_Reports\%1\%1.txt"
sqlcmd -S localhost -d database -i "D:\DataAudit\%1.sql" -s "," > D:\Temp\%1.csv -I -W -k 1
if %ERRORLEVEL% GTR 0 COPY "D:\Temp\%1.csv" "D:\Internal_Reports\%1\%1.txt"
if %ERRORLEVEL% NEQ 0 goto Error_1
echo No Errors
goto end
:Error_1
if %ERRORLEVEL% NEQ 1 goto Error_2
echo No Errors
goto end
:Error_2
echo Errorlevel %ERRORLEVEL%
set FileName=%1%2
echo Filename %FileName%
echo %ERRORLEVEL% > D:\ErrorLevel\%FileName%
EXIT /B %ERRORLEVEL%
:end
SQL File
set NoCount on
DECLARE
#createdBy varchar(16),
#dataAuditBatchId int,
#createdDtTm datetime
select
#createdBy = 'AutomatedAudit'
exec CreateNewDataAuditBatch #createdBy, #dataAuditBatchId output
-- Content Scripts
exec specificAuditStoredProc #createdBy, #dataAuditBatchId
select * from vAuditErrors where JobName in ('specificAuditStoredProc')
:exit(select Case When Counter = 0 then 0 Else 1 End 'errorCode'
from (select CAST(Count(*) AS varchar(4)) AS Counter from vAuditErrors
where JobName in ('specificAuditStoredProc'))
CountTable
)
Your best bet would be PowerShell in this case. You can combine both worlds of Batch Scripting and direct access to SQL.
Copy the below code into a text file: Audit.ps1
Create a File called: AuditFile.txt, put your SpecificAuditProc names on each line.
Then in your batch scheduler run this: "powershell -command "& c:\Audit.ps1 -name 'ProcName'"
Heres the code [Untested]:
param([Parameter(Mandatory=$true)][String]$name="")
$createdBy = "AutomatedAudit"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=LOCALHOST;Database=HT;Integrated Security=True"
$SqlConnection.Open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.Connection = $SqlConnection
$SqlCmd.CommandText = "[CreateNewDataAuditBatch]"
$SqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure
$SqlCmd.Parameters.Add("#createdBy", $creadtedBy)
$SqlCmd.Parameters.Add("#dataAuditBatchId ")
$SqlCmd.Parameters["#dataAuditBatchId"].Direction = [system.Data.ParameterDirection]::Output
$SqlCmd.ExecuteNonQuery()
$dataAuditBatchId = $Command.Parameters["#dataAuditBatchId"].value
$SqlCmd.Dispose()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.Connection = $SqlConnection
$SqlCmd.CommandText = "[$name]"
$SqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure
$SqlCmd.Parameters.Add("#createdBy", $creadtedBy)
$SqlCmd.Parameters.Add("#dataAuditBatchId ", $dataAuditBatchId)
$SqlCmd.ExecuteNonQuery()
$SqlCmd.Dispose()
$sqlcheck = #(Invoke-Sqlcmd -Query "select * from vAuditErrors where JobName in ('$name')" -ServerInstance "LOCALHOST\HT")
if ($sqlcheck.Count -ne 0) {
$sqlcheck > D:\Internal_Reports\$name\$name.txt
$sqlcheck.Count >> D:\ErrorLevel\$name
}
$Connection.Close()
$Connection.Dispose()
This is a simple problem to solve in pure batch PROVIDED you clarify a few points.
What is "%1" here? The database name perhaps?
Do you have just one SQL file and if not, what elements in the sample you posted need to be replaced for different databases?
(sorry - this isn't really an answer per se, but I'll make some (i hope, useful) comments on your btch as posted. The SO comment facility really doesn't suit here...
#echo on
Echo Running SQL Command File for '%1' Data Audit Check
del "D:\Internal_Reports\%1\%1.txt"
sqlcmd -S localhost -d database -i "D:\DataAudit\%1.sql" -s "," > D:\Temp\%1.csv -I -W -k 1
OK: so in all probability, %1 id the database name. So - why -d database and not -d %1 ??
Why the > D:\... and not '-o D:...` ??
if %ERRORLEVEL% GTR 0 COPY "D:\Temp\%1.csv" "D:\Internal_Reports\%1\%1.txt"
Ack! The fail-to-fail scenario in all its glory! Most commonly, you'd get ERRORLEVEL 0 from the sqlcmd BUT COPY can change ERRORLEVEL. If the COPY succeeds, then ERRORLEVEL will be 0, but if COPY fails, ERRORLEVEL would be non-zero and that's the value that will be used by the steps following...
if %ERRORLEVEL% NEQ 0 goto Error_1
echo No Errors
goto end
:Error_1
if %ERRORLEVEL% NEQ 1 goto Error_2
echo No Errors
goto end
You could arrive at :error_2 by simply executing
if errorlevel 2 goto error2
directly after the SQLCMD is executed (means "If errorlevel is 2 OR GREATER")
:Error_2
echo Errorlevel %ERRORLEVEL%
set FileName=%1%2
echo Filename %FileName%
echo %ERRORLEVEL% > D:\ErrorLevel\%FileName%
EXIT /B %ERRORLEVEL%
:end
Suddenly an unexplained %2 appears...?

Resources