Question

When running the following command, sqlcmd.exe writes "Timeout Expired" to the console but the exit code it returns is 0.

sqlcmd.exe -X1 -b -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerThan5Seconds.sql" -E

Please notice I'm purposely setting the querytimeout, -t, to 5 seconds. Also, I'm the -b argument, which I thought should return exit code 1 for errors. I've also tried the -r1 argument and the -m-1 argument to no avail.

I've also looked at the Troubleshooting: Timeout Expired article and noticed that it references an "Error: -2". The sqlcmd.exe documentation for all the arguments related to errors seem to only deal with error codes greater than 0, so perhaps "Timeout expired" is not an error? Also, no matter what arguments I've tried I only see "Timeout expired" as the output, no error code at all.

Lastly, here are all the commands I've tried, only edited to protect server and database names:

C:\>sqlcmd.exe -X1 -b -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E
Timeout expired

C:\>sqlcmd.exe -X1 -b -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -r1
Timeout expired

C:\>sqlcmd.exe -X1 -b -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -V16
Timeout expired

C:\>sqlcmd.exe -X1 -b -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -m-1
Timeout expired

C:\>sqlcmd.exe -X1 -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -m-1
Timeout expired

C:\>sqlcmd.exe -X1 -b -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -r0
Timeout expired

C:\>sqlcmd.exe -X1 -b -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -o "sqlError.txt"

C:\>notepad sqlError.txt

#REM only "Timeout expired" was written to sqlError.txt

C:\>del sqlError.txt

C:\>sqlcmd.exe -X1 -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -m-1
Timeout expired

C:\>sqlcmd.exe -X1 -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -V-3
Sqlcmd: '-V -3': Severity level has to be a number between 1 and 25.

C:\>sqlcmd.exe -X1 -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -V1
Timeout expired

C:\>sqlcmd.exe -X1 -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerTHan5Seconds.sql" -E -r1
Timeout expired

Update: I should note I'm calling this from a C# console application via the Systems.Diagnostics.Process, so I'd like the ExitCode to be 1 if possible. I'm not sure if I can capture ERRORLEVEL.

Further Update: My machine is writing stderr to stdout for some reason, so I'm unable to test the validity of Stefan M's answer. I believe his answer is most likely correct as I've interpreted the documentation for sqlcmd.exe in the same manner. I have another question about why my machine is writing stderr to stdout here.

Was it helpful?

Solution

You can't use -V-3, the lowest value is -V1. In Combination with -b you should get the desired result. The value "ERRORLEVEL" will be set to 1 only if the severity is HIGHER than the value of -V.

My best guess is (not tested):

sqlcmd.exe -X1 -b -S "[ValidServer]" -d "[ValidDatabase]" -t 5 -i "C:\test\ScriptThatRunsLongerThan5Seconds.sql" -E -V1

And then try:

echo %ERRORLEVEL%

The relevant part is:

The value that is returned to the DOS ERRORLEVEL variable is 1 when the SQL Server error message has a severity level greater than 10; otherwise, the value returned is 0. If the -V option has been set in addition to -b, sqlcmd will not report an error if the severity level is lower than the values set using -V

From http://technet.microsoft.com/en-us/library/ms162773.aspx

-b

Specifies that sqlcmd exits and returns a DOS ERRORLEVEL value when an error occurs. The value that is returned to the DOS ERRORLEVEL variable is 1 when the SQL Server error message has a severity level greater than 10; otherwise, the value returned is 0. If the -V option has been set in addition to -b, sqlcmd will not report an error if the severity level is lower than the values set using -V. Command prompt batch files can test the value of ERRORLEVEL and handle the error appropriately. sqlcmd does not report errors for severity level 10 (informational messages).

If the sqlcmd script contains an incorrect comment, syntax error, or is missing a scripting variable, ERRORLEVEL returned is 1.

-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.

This option also sets the sqlcmd scripting variable SQLCMDERRORLEVEL. This variable has a default of 0.

-V error_severity_level

Controls the severity level that is used to set the ERRORLEVEL variable. Error messages that have severity levels greater than or equal to this value set ERRORLEVEL. Values that are less than 0 are reported as 0. Batch and CMD files can be used to test the value of the ERRORLEVEL variable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top