Search notes:

sqlcmd.exe

The sqlcmd utility is very useful because it can be executed from a command line (cmd.exe). It might be the SQL Server counterpart to SQL*Plus.
sqlcmd supersedes osql.

Connect to an instance

In order to connect to the default instance of the SQL Server on the current machine simply use sqlcmd:
C:\> sqlcmd
In order to connect to another instance, use the -S option.
C:\> sqlcmd -S Hostname\InstanceName
If the instance is running on the same server, instead of Hostname, a dot can be used:
C:\> sqlcmd -S .\InstanceName
If the server is running on a non default port, the port number is indicated after a comma:
C:\> sqlcmd -S HOST05,55101
The name of the server can also be stored in the environment variable SQLCMDSERVER. sqlcmd will then use this value if not executed with the -S option.
C:\> set SQLCMDSERVER=SRV03\InstXYZ
C:\> sqlcmd -d TQ84DB -i theScript.sql
In order to create a dedicated administrator connection, the -A option can be used:
C:\> sqlcmd -S . -A

Connecting with username and password

If a user needs to identifed by username and password, these values can be passed using the -U and -P options:
C:\> sqlcmd -S . -U rene -P myBigSecret

Specify the database to connect to

The -d option controls which database sqlcmd connects to (so that there is no need to use the use statement).
C:\> sqlcmd -S … -d myDatabase
The value of the database can also be stored in the environment variable SQLCMDDBNAME.

Executing a script

sqlcmd executes the comma separated list of SQL script files if executed with -i:
C:\> sqlcmd … -i scriptOne.sql,scriptTwo.sql
When sqlcmd executes a script, it might print lots of (n rows affected) messages. In order to turn off such messages, the first statement in the script should be
set nocount on

Execute ad-hoc statements

With the -q and -Q option, »ad-hoc statements« can be executed, that is: statements that are entered in cmd.exe:
C:\> sqlcmd -q sp_who
exit
C:\> sqlcmd -Q sp_who
Both execute the sp_who stored procedure.
The difference between -q and -Q is that -q does not terminate the sqlcmd session after executing the given statement, so it must be explicitly exited. -Q just executes the specified statement and automatically exits.
If the executed statement consists of multiple words, they must be quoted:
C:\> sqlcmd -Q "select col_1, col_2 from tab"

Specifying the batch terminator

The default batch terminator is go which needs to be entered to execute queries.
This default can be changed with the -c option:
C:\> sqlcmd -S … -c ";"
Unfortunately, the ; still needs to be entered on a separate input line.

Writing output to a file

An output file can be stated with the -o option:
C:\> sqlcmd -S Hostname\InstanceName -i f:\project\some\script.sql -o f:\project\output\file.dat
Alternatively, the :out statement can be used within an SQL script to specify a log file. The following script assumes that the environment variable TEMP is already set when sqlcmd is invoked:
:out $(temp)\log.txt

:setVar num 42
:setVar txt "Hello World"

print("The number is $(num), the text is $(txt)");
Github repository about-MSSQL, path: /tools/sqlcmd/out.sql

Set quoted_identifier on

By default, sqlcmd sets quoted_identifier to off. In order to change this default, the -I option is needed:
C:\> sqlcmd … -I …

Authentification options

Credentials for authentification to the Server can be specified with -E, -U and -P.
-E (use Windows authentification) is the default.

Printing (echoing) text

print "hello world"
print "
 
     It's possible to
     print multiple lines
     with one statment, too.

"
print "Quotes must be escaped with another ""quote""."
go
Github repository about-MSSQL, path: /tools/sqlcmd/print.sql

Scripting variables

Defining scripting variables

A scripting variable might be set with :setvar.
In an SQL script, the variable is referenced with $(varName):
:setvar var1 hello
:setvar var2 world

print "$(var1) $(var2)"
go

:setvar words "foo bar baz"
print "$(words)"
go
Github repository about-MSSQL, path: /tools/sqlcmd/setvar.sql
Alternatively, a variable can be set with when sqlcmd is started with the command line option -v varName=varValue.
The following script creates a table with one column and inserts one value into the table. All variables, table name, column name and inserted value, can be dynamically set when sqlcmd is executed with the -i and -y options:
--
--  Call this script with something like
--     sqlcmd -v tab=foo -v col=bar val=baz -i dynamic-table-and-column-name.sql     
--

create table $(tab) (
   $(col)  varchar(10)
)
go

insert into $(tab) values ("$(col)")
go

Showing scripting variables

The currently set scripting variables can be displayed with
:listvar

Predefined scripting variables

print "SQLCMDCOLSEP             = $(SQLCMDCOLSEP)"
print "SQLCMDCOLWIDTH           = $(SQLCMDCOLWIDTH)"
print "SQLCMDDBNAME             = $(SQLCMDDBNAME)"
print "SQLCMDEDITOR             = $(SQLCMDEDITOR)"
print "SQLCMDERRORLEVEL         = $(SQLCMDERRORLEVEL)"
print "SQLCMDHEADERS            = $(SQLCMDHEADERS)"
print "SQLCMDINI                = $(SQLCMDINI)"
print "SQLCMDLOGINTIMEOUT       = $(SQLCMDLOGINTIMEOUT)"
print "SQLCMDMAXFIXEDTYPEWIDTH  = $(SQLCMDMAXFIXEDTYPEWIDTH)"
print "SQLCMDMAXVARTYPEWIDTH    = $(SQLCMDMAXVARTYPEWIDTH)"
print "SQLCMDPACKETSIZE         = $(SQLCMDPACKETSIZE)"
print "SQLCMDSERVER             = $(SQLCMDSERVER)"
print "SQLCMDSTATTIMEOUT        = $(SQLCMDSTATTIMEOUT)"
print "SQLCMDUSER               = $(SQLCMDUSER)"
print "SQLCMDWORKSTATION        = $(SQLCMDWORKSTATION)"

Environment variables

Environment variables that were already set when sqlcmd.exe is invoked can also be used in scripts:
C:\> set TXT=Hello World
C:\> sqlcmd -S … -d … 
1> print("$(TXT), I am $(username)");
2> go

Reading (sourcing) another file

Another SQL script file can be read and executed with the :r command.
:setvar sqlfile read-file.sql
:r file-to-read.sql
Github repository about-MSSQL, path: /tools/sqlcmd/read-file.sql
Variables are passed to the read file
print "

   This file is read
   by $(sqlfile)
   with the :r command
"
Github repository about-MSSQL, path: /tools/sqlcmd/file-to-read.sql

Connecting to another instance

With :connect, it's possible to connect to another instance
:connect Hostname\InstanceName

Raising the error level to suppress informational messages

sqlcmd operates with an error level which is a threshold value that controls which messages are sent to stdout. The higher this threshold value is, the less messages are displayed.
Because the default error level value is 0, even informational messages (such as Changed database context to … are emitted when an sql script executes a use DB statement is executed).
When sqlcmd is invoked, the error level can be set with the -m option.
sqlcmd -m 1 …
Note: the error level that is set with -m should not be confused with the error level that is returned to the caller with :exit(…).

Checking errorlevel in scripts

When a script terminates with an error, it sets the corresponding %errorlevel%.
This can be checked in a .bat file.

run-sql-script.bat

This batch script tries to run the script that is passed as argument.
If sqlcmd encounters an error, it immediately returns (because of the -b option) and sets %errorlevel%. This can be checked by the script
@set script_name=%1

@rem
@rem  Invoke sqlcmd
@rem  Pass it the -b flag so that it terminates
@rem  when it encounters an error
@rem 
@sqlcmd -b -i %script_name% -o run-sql-script.log

@rem
@rem  after calling sqlcmd, we're checking errorlevel
@rem  to find out if the script ran without error.
@rem
@if not errorlevel 1 goto script_ok
   @echo "! Script %script_name% not ok, it returned %errorlevel% !"
:script_ok

The at signs in front of each command prevent cmd.exe from echoing the command when being run.

script-with-error.sql

The following script contains an error.
select "hello world"
go

print this print statement is erroneous
go

select "never reached"
go

script-without-error.sql

This script should be fine
select "this script"
select "hopfully does not"
select "have an error."
go

exit-with-errorcode.sql

This script exits with a specific error code:
:exit (select 42)

run-sql-scripts.bat

run-sql-scripts.bat (note the plural) runs the three scripts.
@call run-sql-script script-with-error.sql
@call run-sql-script script-without-error.sql
@call run-sql-script exit-with-errorcode.sql

sqlcmd statements are executed before the script content is run

It should be noted that sqlcmd statements are executed before the script is run as a batch. Particularly, variable assignments using :setVar might lead to unexpected results if used in an if statement:
if 3<5 begin

   print("This text is printed");
  :setVar txt "first assignment"

end else begin

   print("This text is not printed");
  :setVar txt "second assignment"

end

print("$(txt)");
Github repository about-MSSQL, path: /tools/sqlcmd/preprocessed.sql
This script prints
This text is printed
second assignment

Unable to complete login process due to delay in opening server connection.

I am not really sure when (or why) the error message Sqlcmd: Error: Microsoft ODBC Driver 13 for SQL Server : Unable to complete login process due to delay in opening server connection. occurs, but I was able to connect to a SQL Server instance by increasing the login-timeout value with -l:
sqlcmd -S db.tq84 -l 300

sqlcmd mode in Management Studio

From a query editor in management studio, it's possible to go into sqlcmd mode: Menu Query -> SQLCMD Mode.

See also

:on error exit instructs sqlcmd to immediately abort a script if it encounters an error.
Specifying an sql file to be executed when sqlcmd is invoked.
colon commands
scripts
The executable sqlcmd.exe is located under %programfiles%\Microsoft SQL Server\Client SDK\ODBC\nnn\Binn
SQL Server tools
mssql-cli is a cross-platform command line tool that aims at improving sqlcmd.
Microsoft considers sqlcmd to be a legacy tool. More modern than sqlcmd seems to be mssql-cli.

Links

mssql-scripter is an open source command line tool, written in Python, to access SQL Server.

Index