Specifying relative path to :r command in sqlcmd mode - sql-server

A) Suppose you have four .sql files (script1.sql,script2.sql,script3.sql,script4.sql ) in say in a folder c:\scripts.
B) Create a main script file (Main.sql) with the following, please note I have given relative path for scripts.
:r script1.sql
:r script2.sql
:r script3.sql
:r script4.sql
Save the Main.sql in c:\scripts itself.
C) Create a batch file named "ExecuteScripts.bat" with the following:-
SQLCMD -E -d<YourDatabaseName> -ic:\Scripts\Main.sql
PAUSE
When I run the batch file, its unable to script1.sql file. When i give full path C:\scripts\script1.sql, it works fine but I don't want to hardcode the path here.
Is it possible to achieve this using sqlcmd?

#echo off
pushd "c:\scripts"
SQLCMD -E -d<YourDatabaseName> -iMain.sql
popd
PAUSE
Or if all the sql scripts are in the same folder as your batch script, then:
#echo off
pushd "%~dp0"
SQLCMD -E -d<YourDatabaseName> -iMain.sql
popd
PAUSE
The last version allows your scripts to run properly, no matter where they reside.

What about using complete paths, but creating file Main.sql dynamically?
Batch file which expects the 4 script files in folder of the batch file and creates there also Main.sql.
#echo off
set "BatchFolder=%~dp0"
( echo :r %BatchFolder%script1.sql
echo :r %BatchFolder%script2.sql
echo :r %BatchFolder%script3.sql
echo :r %BatchFolder%script4.sql
)>"%BatchFolder%Main.sql"
sqlcmd.exe -E -d "YourDatabaseName" -i "%BatchFolder%Main.sql"
set "BatchFolder="
pause
Open a command prompt window and run there call /?. The help of this command is output in the window explaining %~dp0 which means drive and path of argument 0 ending with a backslash without surrounding quotes. Argument 0 on running of a batch file is the name of the batch file.
Running in command prompt window set /? results in getting help of command set displayed, listing on last help page some special environment variables defined dynamic on running a batch file. The first one listed is %CD% which means current directory.
So instead of working with folder of batch file, it is also possible to work with current folder on batch execution.
#echo off
set "CurrentFolder=%CD%\"
( echo :r %CurrentFolder%script1.sql
echo :r %CurrentFolder%script2.sql
echo :r %CurrentFolder%script3.sql
echo :r %CurrentFolder%script4.sql
)>"%CurrentFolder%Main.sql"
sqlcmd.exe -E -d "YourDatabaseName" -i "%CurrentFolder%Main.sql"
set "CurrentFolder="
pause
The folder path referenced by %CD% does not end with a backslash like the folder path returned by %~dp0 which is the reason for backslash after %CD% on second line.

Related

Multi-file script execution from command line

I have multiple .sql script files and want to execute them one by one in batch file with proper logging mechanism.
I wrote below batch command to solve the problem
#ECHO OFF
SET SQLCMD="C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\SQLCMD.EXE"
SET PATH="C:\Users\sql_scripts\"
SET SERVER="server_name"
SET DB="database"
SET LOGIN="user_name"
SET PASSWORD="password"
SET OUTPUT="C:\Users\sql_scripts\output\OutputLog.txt"
CD %PATH%
ECHO %date% %time% > %OUTPUT%
for %%f in (*.sql) do (
%SQLCMD% -S %SERVER% -d %DB% -U %LOGIN% -P %PASSWORD% -i %%~f -b >> %OUTPUT%
)
But it has few problems that I want to solve as listed below :
I want to create dynamic out put file names based on input file name. Example if input sql file
name is "test.sql" then I want to create output file in "output" folder with name "test.sql".
Currently It writes all the log to one file i.e. OutputLog.txt
I want to show output log with script of execution to identify which script produced what
output. Let's say in one script file 5 scripts present then in output file I want to show the
script and its output log.

Run command with drag and drop onto batch file

I want to drag and drop a file onto a batch file in order to run the below command on it. How do I go about running the command on the dropped file?
PotreeConverter.exe <dropped file> -o C:/output -p index
The path of the file, when you drop it on the BATfile, will be returned as a normal %1 argument.
so :
#echo off
PotreeConverter.exe "%~1" -o C:/output -p index
You can use %* if you drop more then 1 file
Example :
#echo off
for %%a in (%*) do echo [%%a] was dropped on me
pause
Following this easy guide.
Create a batch file test.bat with the contents
#echo off
echo The full path of the file is: %1
pause
Drag any file onto it, you will see that %1 is replaced with the full path for that file in quotes.
Now you know how to execute some command that takes a path to a file as an argument:
#echo off
some_command_that_takes_a_path_to_a_file %1

User-specified scripts and output folders for sqlcmd in batch file

Currently, the below For/Do loop goes through all SQL files that are in the same folder as the batch file itself and outputs the CSVs to a user-specified folder (%OUTPUTFOLDER% is actually created earlier in the batch file as a subfolder of %SCRIPTFOLDER%, which is specified by the user):
FOR /F "tokens=*" %%S IN (
'DIR /B "%SCRIPTFOLDER%\*.sql" '
) DO (
echo Reading scripts from: %SCRIPTFOLDER%\*.sql
echo Script: %%~fS
echo Output: %OUTPUTFOLDER%\%%~nS.csv
sqlcmd -b -S %INSTANCE% -d %DATABASE% -i "%%~fS" -s "|" -o "%OUTPUTFOLDER%\%%~nS.csv" -W
IF ERRORLEVEL 1 GOTO errorhandling
ECHO %%~nS.csv successfully created
)
For a visual example, if I had the folder structure
C:\Extract\extract.bat
C:\Extract\Scripts\
C:\Extract\Output\
The variable %SCRIPTFOLDER% is set by the user and is the folder that, you guessed it, holds the scripts. But the batch file has to be in that folder, too. I need to change this so that the scripts do not have to be in the same folder as the batch file. I.e. the user can specify both %SCRIPTFOLDER% and %OUTPUTFOLDER%
Due to the output of echo Script: %%fS, I'm guessing that's what I need to change - possibly what's in the FOR line as well, but I'm not seeing how exactly to do that.

Run all SQL files in multiple directories

I combined a couple of solutions I found online to try and make this happen.
https://stackoverflow.com/a/6504317/2471473
https://sqlandme.com/2013/03/25/sql-server-executing-multiple-script-files-using-sqlcmd/
I'm trying to run a single .cmd script (Script1.cmd) with folder locations of .sql files. That single script runs another script (Script2.cmd) to use sqlcmd to execute all the .sql files in that folder location. It mostly works, but it leaves a command window open that I have to exit from for each folder location.
Script1.cmd
start Script2.cmd "C:\Location1"
start Script2.cmd "C:\Location2"
Script2.cmd
#Echo Off
FOR /f %%i IN ('DIR %1\*.Sql /B') do call :RunScript %1 %%i
GOTO :END
:RunScript
Echo Executing Script: %2
cd %1
SQLCMD -S Server123 -d Database456 -E -i %2
Echo Completed Script: %2
:END
Official command line reference for Windows XP or for Windows Server 2003, Windows Vista (and above) seems to be too brief. Read this (extended) start command documentation:
Syntax: START "title" [/D path] [options] "command" [parameters]
Always include a TITLE this can be a simple string like "My Script" or
just a pair of empty quotes "". According to the Microsoft
documentation, the title is optional, but depending on the other
options chosen you can have problems if it is omitted.
If command is an internal cmd command or a batch file then the command
processor is run with the /K switch to cmd.exe. This means that the
window will remain after the command has been run.
Next Script1.cmd should work and close started command windows:
start "" cmd /C Script2.cmd "C:\Location1"
start "" cmd /C Script2.cmd "C:\Location2"

Batch file that unzips and combines contents

I am trying to unzip some folders and then recombine them, however when I run the batch file it get the following error:
'unzip' is not recognized as an internal or external command,
operable program or batch file.
I am guessing I need to point the batch file to where 7-zip is correct? Any insight would be appreciated thanks!
See below for code:
#echo off
cls
:start
:unzip
echo.
echo Unzipping files
echo.
unzip ELMDB-85308-PI003_OVA_2of5.zip
unzip ELMDB-85308-PI003_OVA_3of5.zip
unzip ELMDB-85308-PI003_OVA_4of5.zip
unzip ELMDB-85308-PI003_OVA_5of5.zip
echo.
:combining
echo.
echo Combining parts
echo.
copy /b ELMDB-85308-PI003_OVA_1of4+ELMDB-85308-PI003_OVA_2of4+ELMDB-85308-PI003_OVA_3of4+ELMDB-85308-PI003_OVA_4of4 ELMDB-85308-PI003.OVA
:done
echo.
echo Done!
echo.
pause
:end
Instead of unzip as a command, try 7z -e.
If you copy 7z.exe to some directory that is on your PATH, then you don't need to specify the directory.
You can see your PATH by executing
PATH
from the prompt. This displays a ;-separated list of directories that are searched after the current directory) for executables.
If 7z.exe is not on your PATH, then you'd need
"c:\wherever\it is\7z" -e ....
(more explaining)
If 7z is in your path, then
7Z -e ELMDB-85308-PI003_OVA_2of5.zip
will unzip ELMDB-85308-PI003_OVA_2of5.zip
And you'd then need to add a line for each of the other files (which you have done).
If 7z.exe is not on your path then you need
"C:\Program Files\7-Zip\7z" -e ELMDB-85308-PI003_OVA_2of5.zip
and reproduce that for each of your files.
You can tell that 7z.exe is in your path by executing 7z from the prompt. You will get either a report stating that it's not recognised (ie it's not on your path) or you'll get a commands-and-switches help report (which means it is on your path)
Since the command 7z did not work, then it's not on your path, so you need the other form.
If you were to copy /b C:\Program Files\7-Zip\7z.exe"c:\windows\system32\" then in all probability you'd have 7z.exe on your path and hence you could use the short form.

Resources