I recently had the joy of working through a request to build a VM and have said VM connect to a database server, create a database based on input parameters, create a login based on input parameters and log the results. We did this using VMware App Director. App Director basically allows you to create blue prints that you can use to execute installation packages, scripts, build scripts on the fly and execute…basically the things you want to do after a VM is provisioned from template. I'm not an AppD expert so I wasn't doing the driving, but I was doing much of the SQL scripting and figuring out the nuances that you need to know before ever being successful.
I've done a bunch with SQLCMD, but only in short bursts; work on a project for 3-4 days then move on and forget everything you discovered. This time around I decided to make note of a few of the little issues that popped up and made us miserable test after test. Here we go.
First off, the customer had to create a database remotely and via command line. Naturally my first thought was PowerShell, SQLPS to be more specific. This was the preferred approach, but getting SQL Server PowerShell onto the VM we were deploying meant installing SQL Server Management tools. This isn't entirely bad, unless you've ever tried installing SQL Server Management Studio from the command line…it is a horribly slow process, about 40 minutes. Ok then, scrap that idea.
Next best bet was good old SQLCMD. This is also found in the SSMS package (which you can download separately on the SQL Server Express Download page here) and after suffering through the 40 minute install for the 300KB executable we needed we convinced ourselves that there had to be a better way.
Microsoft SQL Server 2008 R2 Feature Pack
At first glance you want to click the download button, which only gets you a text file. You must expand the Install Instructions section to get to the individual files. In here you find the two components needed to use SQLCMD:
- Microsoft SQL Server 2008 R2 Native Client
- Microsoft SQL Server 2008 R2 Command Line Utilities
Perfect! Two very small packages that can be installed via command-line! Almost.
As it turns out the native client has a EULA which must be accepted, took a while, but we found the answer here. Basically you need to run the command as follows:
Sqlncli.msi /q IACCEPTSQLNCLILICENSETERMS=YES
For the command line utilities no EULA acceptance is required, just use the /q switch to suppress user prompts.
So onto SQLCMD. What we were doing required a connection to a remote SQL Server and creating a bunch of variables that we would refer to in the SQL script we would be invoking. After some trial and error here are a couple of tips:
- When creating a connection to a remote server use –S not –s, the error you receive when using lower-case 'S' is ambiguous and you will pull your hair out.
- When creating variables using SQLCMD to pass to the SQL script the format is SQLCMD –v varDBName1 ="MyDatabase1" varDBName2 ="MyDatabase2" Don't get cute and try using single quotes, it'll bark at you again.
- In Transact-SQL Script you would declare a variable, set the variable and then call the variable. Variables are identified by the first character "@", as in @varDBName1. When setting the variables as part of a SQLCMD command there's no need to declare or set since we are doing so at the command-line. In the above example varDBName1 is presumably referenced in the SQL script that I'm invoking with SQLCMD. The way the variable is referenced in the SQL script changes when using SQLCMD. In my SQL script instead of @varDBName1 I would use $(@varDBName1). For a string the variable should be wrapped in double-quotes as well, "$(varDBName1)".
So, given the following snippet from C:\SQL_Script.sql:
USE master;
GO
SELECT create_date FROM sys.databases WHERE name = $(dbname1)
I would issue the following SQLCMD command:
C:\SQLCMD –S SQL-Server –U User –P Password –v dbname1 ="MyDB" –i c:\sql_script.sql
So, we got what we needed to get done and everyone was happy. I'm happy I got to record all this for everlasting goodness on the interwebs. Now I can purge it from my brain.
-enjoy