Using a condition in a batch script with SQL - sql-server

I'm trying to set up a batch script that basically runs a SQL statement against a database, and if the script returns results it will follow some logic.
Is there a way to have SQLCMD actually return the number of rows it found, or something similar?
I see that I can have the output displayed on the screen or a file, but is there a way to have it put it into a variable so I can have the script evaluate the variable? For example:
SQLCMD -q "select count(*) from active_connections" -r #varactive
IF #varactive > 0 THEN
<do things>
ELSE END
Or would I need to switch to Powershell to handle this sort of logic?

While #Gary is technically correct that the only thing returned is the ERRORLEVEL, sqlcmd does also display its results to STDOUT. Armed with that, you could do something like this in a batch file:
set SERVERNAME=yoursqlserver
for /f "skip=2" %%x in ('sqlcmd -S %SERVERNAME% -Q "select count(*) from active_connections" ^| findstr /v /c:"rows affected"') do set COUNT=%%x
echo There are %COUNT% records in the active_connections table.

See Docs for sqlcmd and you will see quite a few options you probably never paid attention to.
The only thing an executatble "returns" to the batch script environment is the ERRORLEVEL. For SqlCmd you need the -b option to set this (based on the sql server error level)
If you use the -m option, you can control the error messages send to stdout -- I can't test at the moment, but I think this include the rows affected message (a level 0 error perhaps). You would then have to parse this too (ugly in batch scripts)
This sounds like a real kludge at best to be, you are likely better off to use a better scripting environment. PowerShell, Perl, Python, etc. all more powerful and you can find plenty of examples on-line.
Batch is best when you have a "no-deployment" requirement or you needs are simple. Easy to hit the wall as needs change.

Related

How to import file contents into table column as data

A project I'm working on at work involves modifying one of the subsystems to store/pull data that is currently stored in files into the database. Each of the files is a single, sometimes-large, chunk of custom (xml-based) script generated by another custom tool.
Conceptually, I'm looking for an easy way to do something like:
For Each file in folder_and_subfolders
INSERT INTO table
(script_name, version_num, script )
VALUES
({file_name}, 1, {file_contents})
;
Next
Preferably on an entire directory tree at once.
If there's no easy way to do this via T-SQL, I can write a utility to do the job, but I'd prefer something that didn't require having to write another custom tool that will only be used once.
So, I don't have SQL Server installed and therefore can't test this, but if you are looking for a simple batch file that could do what you're after, I'd suggest something like the following might well help;
#echo off
SET xmldir=./myxmlfiles/live/here/
echo --- Processing files
for %%f in ("%xmldir%*.xml") do (echo Running %%f.... && #sqlcmd -I -U %1 -P %2 -S %3 -d %4 -v filename="%xmldir%%%f" -i ProcessFile.sql)
I'm not sure how much you know about sqlcmd, but it is a command line tool that is generally provided by SQL Server. It will allow you to run SQL commands, or in the case above, run a script which is indicated by the -i parameter. I am assuming that you'd place your SQL statement in there to perform your additions to the table.
The other parameters to sqlcmd are described below;
-I sets QUOTED_IDENTIFIER on (you may or may not need this. I did for an earlier issue I faced with sqlcmd and QUOTED_IDENTIFIER)
-U sets the database username
-P sets the database password
-S sets the database server
-d sets the database to connect to
-v is the interesting one here as it lets you pass parameters to your script. Note that on the MSDN page describing this, it states that if your path or filename contains spaces, then you'll need to enclose it in quotes, so check that out. Basically though, you'd be able to refer to the parameter inside your sql script (ProcessFile.sql) like INSERT INTO mytable (file_name) VALUES ('$(filename)')
You'd have to use the logic described in the answer from my previous comment to ensure

Batch file loses logs in loops

I have various test cases in a folder that require me to make continuous loops. To try this I tried making a batch script that would loop the test cases. However the earlier completed iterations would be lost and only the most recent iteration would be kept. How can I keep the XML logs of all the iterations?
My batch file looks like this:
FOR /L %%A IN (1,1,300) DO (
call pybot --name *.robot
)
You will need to have your script tell robot to give a unique name to the output file generated by each iteration of the loop. You will then need an extra step to combine all of those outputs into one.
First, generating unique output files:
FOR /L %%A IN (1,1,300) DO (
call pybot --output output-%%A.xml *.robot
)
Note: by default pybot will generate log.html and report.html. If you want to generate a single unified log and report, you might want to suppress them within the loop. If so, add --log none --report none before the filenames to prevent these files from being created in the loop.
Next, you can use rebot to join all of those individual reports into a single report:
call rebot *.xml
I don't know if rebot is a known command on your system -- it's part of robot but I don't know how you installed things on your system. Generally speaking, if pybot is a valid command, rebot should be too. For more information on rebot see Post-processing outputs in the robot framework user guide.
Note: you seem to have a bug in your batch script. When you do call pybot --name *.robot, the very first file will not get run as a test since it will be given to the --name option rather than be treated as a test file that should be run.
Specify explicitly the log file names, with these parameters:
FOR /L %%A IN (1,1,300) DO (
call pybot --output otput_%%A.html --log log_%%A.html --report report_%%A.html *.robot
)
Have in mind any selenium screenshots will still be overwritten though (if you are using selenium in your tests).
FOR /L %%A IN (1,1,300) DO (
call pybot --name *.robot
)>>afilename.txt

How to write a batch file which processes sql statements

how to write a batch script which will take a file as an input, then it will perform a sql query on that file and give a file as an output.
input will be a textfile which has 4 query in it. Now a batch file is to be written which will take 1 query at a time and execute it and output will be stored in a file. So there will be 4 seperate output file for 4 query
You don't specify which sql server you are using, in this example I will use firebird. If you use a different sql server, you have to use the correct sql commandline tool and syntax. firebird uses isql.exe.
Asuming I have the following text file "input.sql" containing 4 sql commands:
select * from CUSTOMER;
select * from DEPARTMENT;
select * from EMPLOYEE;
select * from SALES;
Then this batchfile will execute each command using isql.exe, and creates a seperate output file for each command:
#echo off
set sql_exe="C:\Program Files\Firebird\Firebird_2_5\bin\isql.exe"
set sql_options=-u sysdba -p masterkey
set sql_db="C:\Program Files\Firebird\Firebird_2_5\examples\empbuild\EMPLOYEE.FDB"
set count=1
for /f "delims=" %%a in (input.sql) do (
echo %%a > temp.sql
call :processtemp_sql
)
goto :eof
:processtemp_sql
%sql_exe% %sql_options% -i temp.sql -o output%count%.txt %sql_db%
set /A count=%count%+1
goto :eof
:eof
at the end output1.txt..output4.txt are created. Each file contains the output of one sql command.
You don't often perform SQL queries on a normal file, it generally requires a DBMS (database management system) at the other end for interpreting the SQL and extracting the relevant data.
Writing a batch file is relatively easy, be it a UNIX shell like bash or the Windows cmd.exe.
But, if you're thinking about implementing a full blown SQL query language that operates on text files (or any non-database file, really), that's probably going to take more then one question on Stack Overflow :-)
Perhaps you could flesh out your question with a little more detail, given that we may have misunderstood your requirements.
I think what you're looking for is Microsoft Log Parser 2.2. It allows you to execute SQL queries on a a number of file types, including logs, CSV and XML files.

Relative path in t sql?

How to get the relative path in t sql? Take for example a .sql file is located in the folder D:\temp, I want to get path of the file hello.txt in the folder D:\temp\App_Data. How to use the relative path reference?
Let's say I am executing the sql file inside the SQL server management studio.
I had a similiar problem, and solved it using sqlcmd variables in conjunction with the %CD% pseudo-variable. Took a bit of trial and error to combine all the pieces. But eventually got it all working. This example expects the script.sql file to be in the same directory as the runscript.bat.
runscript.bat
sqlcmd -S .\SQLINSTANCE -v FullScriptDir="%CD%" -i script.sql -b
script.sql
BULK INSERT [dbo].[ValuesFromCSV]
FROM '$(FullScriptDir)\values.csv'
with
(
fieldterminator = ',',
rowterminator = '\n'
)
go
The .sql file is just.... a file. It doesn't have any sense of its own location. It's the thing that excutes it (which you didn't specify) that would have a sense of its location, the file's location.
I notice that you mentioned an App_Data folder, so I guess that ASP.NET is involved. If you want to use relative paths in your web app, see MapPath
http://msdn.microsoft.com/en-us/library/system.web.httpserverutility.mappath.aspx
The server is executing the t-sql. It doesn't know where the client loaded the file from. You'll have to have the path embedded within the script.
DECLARE #RelDir varchar(1000)
SET #RelDir = 'D:\temp\'
...
Perhaps you can programmatically place the path into the SET command within the .sql script file, or perhaps you can use sqlcmd and pass the relative directory in as a variable.
When T-SQL is executing, it is running in a batch on the server, not on the client machine running Management Studio (or any other SQL client). The client just sends the text contents of the .sql file to the server to be executed. So, unless that file is located on the database server, I highly doubt you're going to be able to interact with it from a SQL script.
The t-sql script is first preprocessed by QueryAnalyzer, SSMS or sqlcmd on the client side. These programs are aware of the file localcation and could easily handle relative pathes similar To Oeacle sqlplus.
Obviously this is just a design decision from Microsoft and I dare say a rather stupid one.
I tried method from mateuscb's comments.
I found it can not work ,i do not know why,then I managed after several test.
It can work with the script below:
runscript.bat
#set FullScriptDir=%CD%
sqlcmd -S .\SQLINSTANCE -i script.sql
script.sql
BULK INSERT [dbo].[ValuesFromCSV]
FROM '$(FullScriptDir)\values.csv'
with
(
fieldterminator = ',',
rowterminator = '\n'
)
go
Just for your information for further discussion.
well it's not a Microsoft thing first off... it's an industry standard thing.
second your solution for running T-SQL with a relative path is to use a batch script or something to inject your path statement IE:
#echo OFF
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ t-SQL.SQL"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
set RunLocation=%~dp0
echo(%~dp0!var! > newsql.sql
ENDLOCAL
)
sqlcmd newsql.sql
or something like that anyway

sqlplus access and email access using shell script

I am fairly beginner level at shell scripts and following are the details..
Am looking for the best way to fire sql queries and and carry out some logic based on that data. I've used the following snippet..
shellvariable=sqlplus $user/$passwd <<END
select count(1) from table1;
end
EOF
if[$shellvariable -ne 0] then
<>
fi
Is there a better way to carry out the same..
you're on the right track. sqlplus is the best way to interact with the database when you are shell scripting, but two things to note:
use the "-S" parameter to stop
sqlplus from printing all its
application info
to read data directly into a variable, you will
need some sqlplus environment
settings to prune back the output to
just what you want
For any DBA's who are learning shell scripting to help them manage and automate Oracle database administration, I would highly recommend Jon Emmons' book Oracle Shell Scripting. It teaches a great shell scripting intro course, but in the context of tasks that are really useful and interesting to DBAs.
One final note: if you are doing anything any more than a simple DBA task, I would recommend not using shell scripts, but use a scripting language that has proper database support. Perl is a good option for Oracle, since it is installed with the database.
Here's an example of a script for Oracle done in both bash and perl. From the shell version, here's how it reads a specific value to a shell variable:
alertlog=$(sqlplus -S \/ as sysdba 2> /dev/null <<EOF
SET NEWPAGE 0
SET SPACE 0
SET LINESIZE 80
SET PAGESIZE 0
SET ECHO OFF
SET FEEDBACK OFF
SET VERIFY OFF
SET HEADING OFF
SELECT value
FROM v\$parameter
WHERE name = 'background_dump_dest';
EOF
)
Accessing database through shell scripting

Resources