How should i include the output of a findstr which retrieves me the name of the stored proc in sqlcmd?
#ECHO OFF
FOR %%f IN ( *.sql) DO (
var xyz = echo %%f | findstr "^test*"
sqlcmd -d databaseX -S server -e -i xyz
)
where xyz will evaluate to testStoredProc1.sql, testStoredProc2.sql and so on.
These stored procs have update/insert and select statement
How can i capture the value of xyz and pipe it to sqlcmd?
#echo off
for %%f in (test*.sql) do (
sqlcmd -d databaseX -S server -e -i %%f
)
NOT TESTED!
For further information check FOR /F , SET ,DelayedExpansion
Related
I use bat script to backup MySQl database
SET SOURCEDIR="C:\Program Files\MariaDB\data\"
set now=%DATE:~-4%-%DATE:~3,2%-%DATE:~0,2%
for /d %%i in (%SOURCEDIR%\*) do (
if not "%%~ni"=="temp" "C:\Program Files\MariaDB\bin\mysqldump.exe" -uroot -h127.0.0.1 -c -e -q --single-transaction=TRUE %%~ni | "c:\Program Files\7-Zip\7z.exe" a -si"%%~ni_%now%.sql" "D:\backup\SQL\%now%\%%~ni.sql.7z"
)
exit
But if database have dot in name, for exapmle data.2023, then MariDB create folder data#002e2023
So SQL dump is empty.
How can I replace #002e to . in this script here *single-transaction=TRUE %%~ni | *?
%%~ni:#002e=!.!% is not working
Based upon your attempt, %%~ni:#002e=!.!%, I'd assume you need to create a variable, and delay variable expansion to use it.
Example:
#Set "SOURCEDIR=%ProgramFiles%\MariaDB\data"
#Set "now=%DATE%"
#Set "now=%now:~-4%-%now:~-7,2%-%now:~-10,2%"
#For /D %%G In ("%SOURCEDIR%\*") Do #If /I Not "%%~nxG" == "temp" (
Set "dirname=%%~nxG"
SetLocal EnableDelayedExpansion
"%ProgramFiles%\MariaDB\bin\mysqldump.exe" -uroot -h127.0.0.1 -c -e -q --single-transaction=TRUE !dirname:#002e=.!^
| "%ProgramFiles%\7-Zip\7z.exe" a -si"%%~nxG_%now%.sql" "D:\backup\SQL\%now%\%%~nxG.sql.7z"
EndLocal)
im trying to create a batch file that goes thorugh each text file in a folder and looks for specific words such as "msg" "file" "size" in each line. If those words are found then it sends and me an email.
Im using SQL server to send the email, and im calling the email stored procedure from my batch file like this:
set MYDB= yourDBname
set MYUSER=youruser
set MYPASSWORD=yourpassword
set MYSERVER=yourservername
sqlcmd -S %MYSERVER% -d %MYDB% -U %MYUSER% -P %MYPASSWORD% -h -1 -s "," -W -Q "exec yourstoredprocedure"
I just need help writing the script which checks for specific words in each line in each .txt file
Just give a try for this batch file :
#echo off
Title Search String into text files
Set "ROOT=%~dp0"
set "String2Search=msg size file"
For %%a in (%String2Search%) do (
FOR /f "delims=" %%f IN ('dir /b /s "%ROOT%\*.txt"') DO (
(find /I "%%a" "%%f" >nul 2>&1) && ( Call :FoundString "%%a" "%%f" ) || ( Call :NoFound "%%a" "%%f" )
)
)
pause & exit
::*************
:FoundString
echo found %1 on file %2
goto :eof
::*************
:NoFound
echo no string like %1 found on file %2
goto :eof
::*************
Few suggestions as i cannot comment.I had done a project few years back and i had to do search files with a particular extension and read them to find particular words and do something with them.I remember few things only.I hope it helps you.
To find all txt files:
find /home/user/Downloads/etc -name '*txt'
To read a whole file and search for "msg" "file" "size":
while read -r LINE
do
grep -i "msg" | grep -i "file" | grep -i "size"
to check all in one line
Or you can do it executing one by one without "pipelining".
P.S I don't have linux installed otherwise I would have checked before posting.Sorry if not correct.
This should do the job:
#ECHO OFF
CD C:\wherever\your\.txt\files\are\at
FOR /R %%G IN ("*.txt") DO (FINDSTR /I /C:"msg" /C:"file" /C:"size" "%%G" >nul && GOTO match_found)
GOTO no_match
:match_found
ECHO Match found^!
set MYDB= yourDBname
set MYUSER=youruser
set MYPASSWORD=yourpassword
set MYSERVER=yourservername
sqlcmd -S %MYSERVER% -d %MYDB% -U %MYUSER% -P %MYPASSWORD% -h -1 -s "," -W -Q "exec yourstoredprocedure"
:no_match
ECHO No match found^!
PAUSE
If the batch file is in the same folder as the .txt files you can delete the CD line.
If the search should be case-sensitive remove the /I option.
To satisfy your question as asked, this should suffice:
#Echo Off
FindStr /IR "\<msg\> \<file\> \<size\>" "C:\Users\NT-Hero\*.txt">Nul||Exit /B
Rem Your 'match found' commands here
If you wanted to also search in sub-directories change the FindStr options to /SIR. (See FindStr /? for more options).
I have a very simple batch file that runs a SQL query file and copies the results to a printer. The problem is it prints even if the results of the query is 0 rows. How can I only print if there is data?
cd stock
sqlcmd -i testquery.sql -S localhost -U User -P password -o testresults.txt
copy testresults.txt \\printserver\share
sqlcmd -i ems_update.sql -S localhost -U User -P password
del c:\stock\testresults.txt
exit
Ok, this is what I have now:
cd c:\stock
sqlcmd -i testquery.sql -S localhost -U User -P password -o testresults.txt
#find /c /i "0 rows" "C:\stock\testresults.txt" > NUL
if %ERRORLEVEL% EQU 1 (
pause
) else (
copy c:\stock\testresults.txt \\printserver\share)
pause
sqlcmd -i ems_update.sql -S localhost -U User -P password
I cannot get the copy command to run now. What am I missing??
thanks
Take a file that you know has 0 data.for /f "delims=" %%A in ('type nodata.txt') do set nodata=%%AThenfor /f "delims=" %%A in ('type testresults.txt') do set test_result=%%AThenif not %nodata%==%test_result% copy testresults.txt \printserver\shareThis will only work if the same exact no data file is produced, like no timestamps.or
use find which returns %errorlevel%==1 if it does not find a phrase in file and 0 if it does.
Just an idea - you can check if size of the file is 0. In Bash it would be something like this:
if [ ! -s ./testresults.txt ] ; then
rm ./testresults.txt
# or do something else
else
copy testresults.txt \\printserver\share
fi
I'm using SQLCMD to get the count of rows in a table, but I also want to be aware if the query hits an error.
The sqlcmd I'm using looks like this:
sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
If it works, it will return:
-----------
10205
(1 rows affected)
(Note, there is a blank line above the ------- for the column name I'm not specifying.)
If I pass in a table that doesn't exist, I get the following response:
Msg 208, Level 16, State 1, Server devServer, Line 1
Invalid object name 'dbo.no_table'.
Since I have the -b flag, I can check ERRORLEVEL for a value (in this case, 1).
To store the count variable, I've been using the following line:
for /F %%i in ('sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%" ^| findstr /r "[^(][0-9]"') do SET /a rec_count=%%i
After the for, %errorlevel% returns 0. Even inside the do, errorlevel is 0.
Is there any simple way to run sqlcmd, store the count if there is not an error, and print both lines if there is an error?
Commands that are executed by FOR /F are implicitly executed via a new CMD session. For example, with for /f %a in ('echo hello') do ..., the command that is executed becomes C:\Windows\system32\cmd.exe /c echo hello.
Your command is properly setting the ERRORLEVEL, but then the value is lost as soon as the child CMD session terminates and control is returned to your batch script.
So the /b option is not really doing any good for you, and can be dropped.
You can suppress the header info by adding the -h -1 option.
You can suppress the (1 rows affected) message by prefixing your command with set nocount on;
You can add the -r 1 option to cause error messages to appear on stderr instead of stdout. This will prevent FOR /F from processing any error, and the error message will appear on the screen instead.
You can clear the rec_count variable before you execute the command. Then it will remain undefined if there was an error, else it will contain the count if there was no error.
set "rec_count="
for /f %%A in (
'sqlcmd -S %server% -U %user% -P %pass% -h -1 -r 1 -Q "set nocount on;select count(*) from %table%"'
) do set "rec_count=%%A"
if not defined rec_count echo There was an error!
One other thing you might consider is using environment variables recognized by SQLCMD for your server, username, and password. Then you won't have to use the -S, -U, or -P options. This is especially handy if your batch script runs many SQLCMD commands.
set "sqlcmdServer=YourServer"
set "sqlcmdUser=YourUserName"
set "sqlcmdPassword=YourPassword"
set "rec_count="
for /f %%A in (
'sqlcmd -h -1 -r 1 -Q "set nocount on;select count(*) from %table%"'
) do set "rec_count=%%A"
if not defined rec_count echo There was an error!
The reason errorlevel does not seem to be getting set is because the for command is executing successfully, regardless of how the code that it loops through executes. So you can only interact with the errorlevel that is set by the sqlcmd command on the same line (inside the for loop brackets).
You should be able to use || (double pipe) after the sqlcmd command. Any code after || will only run if the previous command fails. Example:
notACommand || echo test
Will return "test". While the following will output only "a command":
echo a command || echo test
I can't test it, but something like the following should work for you:
for /F "EOL=(" %%i in ('sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%" ^|^| echo fail') do (
SET rec_count=%%i
)
if "%rec_count%"=="fail" echo SQL command failed
If the output is exactly as you say, then you should not need the findstr command - just set ( open bracket as an EOL character in the for loop, so you effectively drop the "(1 rows affected)" line. You will probably want to use the variables differently, but this is just one way you can tell if the sqlcmd command has failed or not.
As for outputting the error - a bad solution is to run the same sqlcmd command again. Something like the following:
set command=sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
for /F "EOL=(" %%i in ('%command% ^|^| echo fail') do SET rec_count=%%i
if "%rec_count%"=="fail" (%command%) else echo rec_count is %rec_count%
Note that I removed the /a switch when setting the rec_count variable, because it can now be set as a word.
I'm trying to set the output of a sqlcmd query to a variable in a batch file.
Here's my query:
sqlcmd -S <SERVER> -d <DATABASE> -Q "select max(Column1)+1 from Table1"
This gives me exactly what I would expect and what I want:
-----------
10
<1 rows affected>
However, when I try to set it to a variable, I used this script:
for /f %%a in ('sqlcmd -S <SERVER> -d <DATABASE> -Q "select max(Column1)+1 from Table1"')
do set ColumnVar=%%a
echo %ColumnVar%
pause
This gives me this result instead: <1 rows affected> I'm guessing this is because the loop is setting the variable to the last line. So is there a way I could use tokens and delims to parse out the 10 instead?
Try turning on NOCOUNT:
for /f %%a in ('sqlcmd -S <SERVER> -d <DATABASE> -Q "SET NOCOUNT ON; select max(Column1)+1 from Table1"') do set ColumnVar=%%a
echo %ColumnVar%
pause