SQLCMD with 1 return value - batch-file

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)'

Related

Concatenate text in batch

I have sql files in a folder structure like the following :
C:\Users\Peter\Desktop\SQL_FILES\data_structure\customer1\test.sql
C:\Users\Peter\Desktop\SQL_FILES\data_structure\customer2\test.sql
C:\Users\Peter\Desktop\SQL_FILES\data_structure\customer3\test.sql
C:\Users\Peter\Desktop\SQL_FILES\data_structure\customer4\test.sql
........
I want to make a script which reads the path (C:\Users\Peter\Desktop\SQL_FILES),
the name of the file(test.sql) and a text
and then concatenate the text in the end of each test.sql file.
Could you help me please ?
Thanks in advance
:: Hide Command and Set Scope
#echo off
setlocal EnableExtensions
mode 140,50
set /p AbsolutePath="Enter the path of root folder :"
echo.
set /p FileName="Enter the filename with it's extension (ie. test.sql):"
echo.
echo Enter your inserts
echo Press Enter twice when finished
echo (text may not contain ^<, ^>, ^|, ^&, or un-closed quotes)
ver > NUL
set new_line=""
:still_typing
set /p new_line=">"
if errorlevel 1 echo. >> temp.txt & set /p new_line=">"
if errorlevel 1 echo Sending message. . . & goto done_typing
echo %new_line% >> temp.txt
goto still_typing
:done_typing
echo done
:End
endlocal
pause >nul
=====================================
For example :
The file test.sql for example contains initially :
INSERT INTO TEST(COL1,COL2,COL3) VALUES(3,4,5);
And after the execution of batch supposing I add an empty line and two inserts in the text :
INSERT INTO TEST(COL1,COL2,COL3) VALUES(3,4,5);
INSERT INTO TEST(COL1,COL2,COL3) VALUES (1,2,3);
INSERT INTO TEST(COL1,COL2,COL3) VALUES (2,3,4);
The Batch file below use a different method to do the same, but in a simpler way. This code may be modified in any point you wish; for example, if you want not that the filename must include a wild-card.
#echo off
setlocal
set /p "AbsolutePath=Enter the path of root folder: "
echo/
set /p "FileName=Enter the filename with a wild-card (ie. test*.sql): "
echo/
echo Enter your inserts
echo Press Ctrl-Z and Enter when finished
copy CON temp.txt > NUL
echo/
echo Typing done
echo/
for /R "%AbsolutePath%" %%a in (%FileName%) do type temp.txt >> "%%a"

Batch file loosing variables in FOR loop

I am struggling with this one for some time now. Tried WITH and WITHOUT EnableDelayedExpansion, but no joy. Simply, the variable %MYFILENAME% is empty right after it's set in a loop:
::echo off
setlocal enabledelayedexpansion
echo -- BACKUP DATABASES --
set MYPATH=D:\SQL_BACKUP
set MYDBASES=db1 db2 db3 db4
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set MYDATE=%%c%%a%%b)
For /f "tokens=1-2 delims=/:" %%a in ("%TIME%") do (set MYTIME=%%a-%%b)
set MYDATE=%MYDATE:.=-%
for %%q in (%MYDBASES%) do (
echo DB %%q processing
set MYFILENAME=%MYPATH%\%%q_%MYDATE%_%MYTIME%.bak
set SERVERNAME=.
echo %MYFILENAME%
echo sqlcmd -B -E -S %SERVERNAME% -d master -Q "BACKUP DATABASE [%%q] TO DISK = N'%MYFILENAME%' WITH INIT , NOUNLOAD , NAME = N'%%q backup', NOSKIP , STATS = 10, NOFORMAT"
if %ERRORLEVEL% == 0 (
echo OK
) else if %ERRORLEVEL% == 1 (
echo failed!
)
)
echo.
set MYDATE=
set MYTIME=
set BACKUPFILENAME=
set MYPATH=
set MYDBASES=
set MYFILENAME=
What I get is lost %MYFILENAME% imediatelly:
echo DB db1 processing
set MYFILENAME=db1_11-11-2016_0-54.bak
set SERVERNAME=.
echo <<<----------HERE MISSING MYFILENAME ----------<<<
echo sqlcmd -B -E -S . -d master -Q "BACKUP DATABASE [zdvrhnika] TO DISK = N''
WITH INIT , NOUNLOAD , NAME = N'zdvrhnika backup', NOSKIP , STATS = 10, NOFORMAT
"
Any idea?
EDIT
After changing MYFILENAME and SERVERNAME variables to some simple texts, I found out, that they do not change at all! MYFILENAME is always empty, and SERVERNAME is always ".", regardless of what I set them to?! And regardless of whether I use SETLOCAL EnableDelayedExpansion or not.
It's not script fault, but some environment stuff.
Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion **and use !var! in place of %var% to access the changed value of var ** or 2) to call a subroutine to perform further processing using the changed values.

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.

windows batch file executing sql server query

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.

Touch file to update the date/time of file? (Modified Date) (WindowsXP BatchScript)

What's a batch script command to touch on a file to update its date and time to the current date and time? (Modified Date)
For example, Joe Blow sends me a text document which he created months ago, when he emails me the document, I want to keep track of how old it is from the day I received it (not when he created it) so I want to update the file's date/time to the current date/time.
I have a batch script to automatically weed out files that haven't been edited within 90 days, so this is troublesome when I receive a particularly older file then all of a sudden it disappears.
And I need it via a batch script as I have hundreds of files to manage, and it's for archiving files.
I can't take all the credit, but I did look through my todo.txt to find it
Microsoft "touch" it's a KB article from like 5 years ago
The jist of it is you use copy /b MYFILENAME +,, where MYFILENAME is your file
This is an expansion on aflat's anwer.
1) Microsoft support provides an explanation and simple touch.bat script.
2) My custom touch.cmd, which expands on the MS script by including "touch /?" help text.
3) My custom midastouch.cmd, which provides several options including recursive operation and date operations.
As aflat wrote, the simple answer is:
copy /b FILENAME +,,
As you might expect, FILENAME can include relative or absolute path and wildcards like *.txt.
1. Microsoft1 support:
The following MS-DOS command updates the date and time stamps of a
file named "EXAMPLE" without altering the contents of the file. This
is similar to the TOUCH utility found in XENIX and in some third-party
MS-DOS toolkits.
COPY /B EXAMPLE +,,
The COPY command can concatenate a file onto an existing file when
used in the form:
COPY FILE1+FILE2
In this example, the contents of FILE2 are appended to FILE1, leaving FILE2 unchanged. When copying in this mode, the COPY command
switches to ASCII mode where the ^Z (0x01A) end-of-file marker is
honored.
Therefore, with the above command, the /b forces the COPY command into
binary mode, the filename is the file to be updated, the + (plus sign)
indicates that a file is to be appended, and the ,, (commas) are
placeholders for the remaining parameters (which are not included in
this example). Because the file to be appended is not specified, the
COPY command will append nothing and only update the time and date
stamps for the file.
The following batch file, TOUCH.BAT, can be used to automate the
process:
#echo off
if %1.==. goto end
if not exist %1 goto end
copy /b %1 +,, > nul
echo %1 touched!
:end
This batch file requires one parameter, the file to be "touched." If the
parameter is not supplied, line 2 will cause the batch file to
exit without doing anything. If the specified file does not exist,
line 3 will cause the batch file to exit also.
2. Touch.cmd
#echo off
:: -----------------------------------------
:: Process input parameter
:: -----------------------------------------
: Help requestes?
if "%1%"=="/?" goto help
if "%1%"=="?" goto help
if "%1%"=="" goto help
:: -----------------------------------------
:: Update Modified Date property to now
:: -----------------------------------------
if not exist %1% goto end
copy /b %1% +,, > nul
echo %1 touched!
goto end
:help
#echo off
echo :: --------------------------------------------------------------
echo :: Touch.cmd Help
echo :: --------------------------------------------------------------
echo.
echo Touch.cmd is batch script to update the Modified Date property
echo of teh specified file to the current
echo date and time.
echo.
echo Syntax: touch filename
echo where,
echo filename is the name of the name of the file to "touch."
echo filename may include a relative o full path.
echo filename may include wild cards like *.txt.
echo.
:end
3. MidasTouch.cmd
#echo off
:: -----------------------------------------
:: Find files older than specified date
:: -----------------------------------------
:: -----------------------------------------
:: Default Values
:: -----------------------------------------
set "default_path=%cd%"
set "default_err_log=%cd%\midastouch_err.log"
set /a default_date=-365
set "open_log=False"
set "recurse=True"
:: -----------------------------------------
:: Process input parameters
:: -----------------------------------------
: Help requestes?
if "%1%"=="/?" goto help
if "%1%"=="?" goto help
if /I "%1%"=="help" goto help
set "dir_in="
set "err_log="
set "dd="
:: Read in commandline arguements.
echo Arguements:
:arguement_loop
if "%1%"=="/p" (
echo Path: %2%
set dir_in=%2%
shift
goto loop_bottom)
if "%1%"=="/l" (
echo Error log: %2%
set err_log=%2%
shift
goto loop_bottom)
if "%1%"=="/-l" (
echo No error log. Output to console.
set err_log=CON
shift
goto loop_bottom)
if "%1%"=="/d" (
echo Date: %2%
set /a dd=%2%
shift
goto loop_bottom)
if "%1%"=="/o" (
echo Open log: True
set "open_log=True"
goto loop_bottom)
if "%1%"=="/-o" (
echo Open log: False
set "open_log=False"
goto loop_bottom)
if "%1%"=="/s" (
echo Recursive: True
set "recurse=True"
goto loop_bottom)
if "%1%"=="/-s" (
echo Recursive: False
set "recurse=False"
goto loop_bottom)
if not "%1%"=="" (
if "%dir_in%"=="" (
echo Path: %1%
set dir_in=%1%
goto loop_bottom)
if "%err_log%"=="" (
echo Error log: %1%
set err_log=%1%
goto loop_bottom)
if "%dd%"=="" (
echo Date: %1%
set /a dd=%1%
goto loop_bottom)
)
:loop_bottom
shift
if not "%1%"=="" goto arguement_loop
if "%dir_in%"=="" (
set dir_in=%default_path%)
if "%err_log%"=="" (
set err_log=%default_err_log%)
if "%dd%"=="" (
set /a dd=%default_date%)
:: -----------------------------------------
:: Execution
:: -----------------------------------------
:: Write header
set "header=Touch_dir.cmd Error Log"
if exist %err_log% (
del /q %err_log%)
#echo %header% >%err_log%
set cmd_str="cmd /c copy /b #path +,,"
:: Update Modified Date property to now
if /I "%recurse%"=="True" (
set cmd_str=forfiles /s /p %dir_in% /d %dd% /c %cmd_str%
) else (
set cmd_str=forfiles /p %dir_in% /d %dd% /c %cmd_str%
)
echo Command: %cmd_str% >>%err_log%
echo Errors: >>%err_log%
echo. >>%err_log%
echo Executing command: %cmd_str%
#echo Updating Modified Date of files older than date: %dd%.
#echo This may take a while. Please be patient...
#echo.
echo.
set cmd_str=%cmd_str% || #echo Failed to update: #path >>%err_log%"
%cmd_str%
:: Results
#echo Error log: %err_log%
if "%open_log%"=="True" (start %err_log%)
goto end
:help
#echo off
echo :: --------------------------------------------------------------
echo :: Touch_dir.cmd Help
echo :: --------------------------------------------------------------
echo.
echo Touch.cmd is batch script to recursively "touch" all files in a
echo folder to update their Modified Date property to the current
echo date and time.
echo.
echo Syntax: touch_dir /d directory /l err_log /m months
echo where,
echo /p path Path containing files with Modified
echo Date values to update to now.
echo (default = current directory).
echo /s (or /-s) Recursive (or not recursive) search
echo (default recursive is %recurse%).
echo /l err_log Error log: list of files not updated
echo (default err_log: midastouch_err.log).
echo /o (or /-o) Open (or do not open) error log after
echo execution (default open_log: %open_log%).
echo /d date Selects files with a last modified date greater
echo than or equal to (+), or less than or equal to
echo (-), the specified date using the
echo "MM/dd/yyyy" format; or selects files with a
echo last modified date greater than or equal to (+)
echo the current date plus "dd" days, or less than or
echo equal to (-) the current date minus "dd" days. A
echo valid "dd" number of days can be any number in
echo the range of 0 - 32768.
echo "+" is taken as default sign if not specified.
echo (default date is: %default_date%).
echo.
:end
Just to add that the same source provide a batch script.
#echo off
goto start
:usage
echo usage: TOUCH.BAT "MYFILENAME"
exit /b 0
:start
if %1.==. goto usage
if not exist %1 goto usage
copy /b %1 +,, > nul
echo %1 touched!
exit /b 0

Resources