Return value of SQLCMD - sql-server

I need to check the exit status (success/failure) of a query run through SQLCMD utility. For example, the server I am connecting doesn't have a database name EastWind. Then, the command below fails with the message ...
> "C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE"
-S ZEPHIR -E -Q "USE WestWind"
Changed database context to 'WestWind'.
> echo %errorlevel%
0
> "C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE"
-S ZEPHIR -E -Q "USE EastWind"
Database 'EastWind' does not exist. Make sure that the name is entered correctly
> echo %errorlevel%
0
I see that the return value is the same in both the cases. How can I check if a command has failed in SQLCMD?

You need to use the -V option
Note: That's a capital -V, not a lowercase -v.
Example:
> SQLCMD.EXE -S whatever -E -V16 -Q "USE does_not_exist"
Msg 911, Level 16, State 1, ...
Could not locate entry ...
> echo %ERRORLEVEL%
16
Update: Alternatively, you can use the -b option, which has different semantics to the execution (the whole batch stops on the first error). YMMV.
Example:
> SQLCMD.EXE -S whatever -E -b -Q "USE does_not_exist"
Msg 911, Level 16, State 1, ...
Could not locate entry ...
> echo %ERRORLEVEL%
1
You can also combine -b and -V.

I am not sure, but did you tried SQLCMD -m switch? sqlcmd Utility
-m error_level - Controls which error messages are sent to stdout. Messages that have a severity level greater than or equal to this level are sent. When this value is set to -1, all messages including informational messages, are sent. Spaces are not allowed between the -m and -1. For example, -m-1 is valid, and -m -1 is not.

Related

BCP command in Linux doesn't return the proper error code

In Linux/Unix based systems, whenever we execute a command in the shell and we echo the $?, the return value is 0 when its a success and the return value is 1 if the command fails.
So, if I am using the BULK COPY utility called BCP for SQL Server, and if the command fails when there is an error with the source file. For example, if I execute a bcp command like this.
/opt/bin/bcp <tablename> in <source_file> -S -U -P -D
and it says. "0 Rows Copied". It might be due to some errors in the source file. And, after that I do a echo $?. The value returned is still 0.
Is there a way we can capture the return value as 1, when encountered an error?
Thanks.
BCP doesn't document any return value. That's a shortcoming. What you can do is redirect output to a file, and look for error indications (probably, the text "Error").
To add a bit more detail to TT.'s answer, I write the bcp output to another file and then grep through it. My code looks like...
/opt/mssql-tools/bin/bcp "$TABLENAME" in $f \
-S $DEST_IP \
-U $USER -P $PASSWORD \
-d $DEST_DB \
-c \
-t "\t" \
-e $EXPORT_STAGE/$TABLENAME/$TABLENAME.$(basename $f).bcperror.log \
| tee $EXPORT_STAGE/$TABLENAME/$TABLENAME.$(basename $f).bcprun.log
# note here that I preserve the bcp output to can later in script
# look for error messages in the bcp process run itself (manually done since bcp does not throw error codes)
echo -e "\n Checking for error messages in bcp output\n"
if grep -q "Error" $EXPORT_STAGE/$TABLENAME/$TABLENAME.$(basename $f).bcprun.log
then
echo -e "\n\nError: error message detected in bcp process output, exiting..."
exit 255
fi
# can delete since already printing to stdout as well (and can just log the whole thing)
rm -f $EXPORT_STAGE/$TABLENAME/$TABLENAME.$(basename $f).bcprun.log

BCP utility incorrect syntax

What is incorrect about this syntax?
bcp transitschedule in calendar_dates.txt -T -f calenar_dates.fmt -F 2
I have tried this through sqlcmd and SSMS to a database on Azure. When I run the command I get:
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'in'.
Yet, the examples here are not very much different syntactically. If I add database name or schema name error shifts towards the period.
Like SQLCMD, BCP is a stand-alone command-prompt utility that must be invoked from a command prompt. If the source text and format files reside on your client, you'll need to add the -S -U and -P parameters like you do with SQLCMD. For example:
bcp databasename.schemaname.transitschedule in calendar_dates.txt -f calenar_dates.fmt -F 2 /S azure-database-server /U azure-database_login /P azure-database-password

Error While using SQLCMD in PDW

I'm using SQLCMD in PDW for extracting data into a flat file. The command line syntax is given below:
sqlcmd -S "10.20.30.40,19001" -d MyPDW_DB -U PDW_User -P Password1 -Q "SET QUOTED_IDENTIFIER ON; SELECT * FROM MyPDW_DB.dbo.SampleFact" -o "FactOut.txt" -s"|"
When I try to execute the batch file, I get the following error:
Msg 104409, Level 16, State 1, Server PdwTdsServer, Line 1
Setting QuotedIdentifier to 'OFF' is not supported.
I am assuming this is due to the fact that there is a "comma" in the server name (IP address,Port Number). I can use this command for extracting data from SQL tables. Any idea on how I can make this working for PDW?
Thanks in advance
I got this working partially.
sqlcmd -S "10.20.30.40,19001" -d MyPDW_DB -U PDW_User -P Password1 -I -Q "SELECT * FROM MyPDW_DB.dbo.SampleFact" -o "FactOut.txt" -s"|"
For setting the quoted_identifier OFF, the option to use is "-I". However, I'm still trying to find an alternative for "SET NOCOUNT ON" option which is not supported in PDW. If someone can help me with that, I'd greatly appreciate that.

How to get the SQL Server script error in a batch File

I am calling an SQL Server script on a batch file, but I need get the error(when the script fail) in the batch file, what can I do?
This is the batch file:
sqlcmd -S HOST -U User -P password -i test.sql
echo %errorlevel%
and this is the Script File(Test.sql):
USE TrainingSitecore_Web
go
SELECT * FROM items
go
RAISERROR ('This is a test Error.',-- Message text.
16,-- Severity.
1 -- State.
);
Make sense?
It can be done using -r parameter:
Example:
sqlcmd -Q "select 1 as a; select 1/0 as b" -E -r1 1> NUL
-r[ 0 | 1] msgs to stderr
Redirects the error message output to the screen (stderr). If you do
not specify a parameter or if you specify 0, only error messages that
have a severity level of 11 or higher are redirected. If you specify
1, all error message output including PRINT is redirected. Has no
effect if you use -o. By default, messages are sent to stdout.
MSDN for more

Check database connectivity using Shell script

I am trying to write a shell script to check database connectivity. Within my script I am using the command
sqlplus uid/pwd#database-schemaname
to connect to my Oracle database.
Now I want to save the output generated by this command (before it drops to SQL prompt) in a temp file and then grep / find the string "Connected to" from that file to see if the connectivity is fine or not.
Can anyone please help me to catch the output and get out of that prompt and test whether connectivity is fine?
Use a script like this:
#!/bin/sh
echo "exit" | sqlplus -L uid/pwd#dbname | grep Connected > /dev/null
if [ $? -eq 0 ]
then
echo "OK"
else
echo "NOT OK"
fi
echo "exit" assures that your program exits immediately (this gets piped to sqlplus).
-L assures that sqlplus won't ask for password if credentials are not ok (which would make it get stuck as well).
(> /dev/null just hides output from grep, which we don't need because the results are accessed via $? in this case)
You can avoid the SQL prompt by doing:
sqlplus uid/pwd#database-schemaname < /dev/null
SqlPlus exits immediately.
Now just grep the output of the above as:
if sqlplus uid/pwd#database-schemaname < /dev/null | grep 'Connected to'; then
# have connectivity to Oracle
else
# No connectivity
fi
#! /bin/sh
if echo "exit;" | sqlplus UID/PWD#database-schemaname 2>&1 | grep -q "Connected to"
then echo connected OK
else echo connection FAIL
fi
Not knowing whether the "Connected to" message is put to standard output or standard error, this checks both. "qrep -q" instead of "grep... >/dev/null" assumes Linux.
#!/bin/bash
output=`sqlplus -s "user/pass#POLIGON.TEST " <<EOF
set heading off feedback off verify off
select distinct machine from v\\$session;
exit
EOF
`
echo $output
if [[ $output =~ ERROR ]]; then
echo "ERROR"
else
echo "OK"
fi
Here's a good option which does not expose the password on the command line
#!/bin/bash
CONNECT_STRING=<USERNAME>/<PASS>#<SID>
sqlplus -s -L /NOLOG <<EOF
whenever sqlerror exit 1
whenever oserror exit 1
CONNECT $CONNECT_STRING
exit
EOF
SQLPLUS_RC=$?
echo "RC=$SQLPLUS_RC"
[ $SQLPLUS_RC -eq 0 ] && echo "Connected successfully"
[ $SQLPLUS_RC -ne 0 ] && echo "Failed to connect"
exit SQLPLUS_RC
none of the proposed solutions works for me, as my script is executed in machines running several countries, with different locales, I can't simply check for one String simply because this string in the other machine is translated to a different language. As a solution I'm using SQLcl
https://www.oracle.com/database/technologies/appdev/sqlcl.html
which is compatible with all sql*plus scripts and allow you to test the database connectivity like this:
echo "disconnect" | sql -L $DB_CONNECTION_STRING > /dev/null || fail "cannot check connectivity with the database, check your settings"
#!/bin/sh
echo "exit" | sqlplus -S -L uid/pwd#dbname
if [ $? -eq 0 ]
then
echo "OK"
else
echo "NOT OK"
fi
For connection validation -S would be sufficient.
The "silent" mode doesn't prevent terminal output. All it does is:
-S Sets silent mode which suppresses the display of
the SQL*Plus banner, prompts, and echoing of
commands.
If you want to suppress all terminal output, then you'll need to do something like:
sqlplus ... > /dev/null 2>&1
This was my one-liner for docker container to wait until DB is ready:
until sqlplus -s sys/Oracle18#oracledbxe/XE as sysdba <<< "SELECT 13376411 FROM DUAL; exit;" | grep "13376411"; do echo "Could not connect to oracle... sleep for a while"; sleep 3; done
And the same in multiple lines:
until sqlplus -s sys/Oracle18#oracledbxe/XE as sysdba <<< "SELECT 13376411 FROM DUAL; exit;" | grep "13376411";
do
echo "Could not connect to oracle... sleep for a while";
sleep 3;
done
So it basically does select with magic number and checks that correct number was actually returned.

Resources