It is worth pointing out that :setvar variables are not like variables in a programming language. They are more like constants. I think it works this way: SQLCMD evaluates the value of $(VarName) just once when the script is parsed.
The $(VarName) variables can be set as follows:
1. :setvar VarName a constant string
2. VarName is an environment variable
3. The sqlcmd command line -v VarName=value
This limits the use of :setvar. For instance:
1. you cant select a value from a table and place it in $(VarName) using :setvar.
2. You cant use :setvar in a T-SQL loop.
3. You cant use @VarName variables as parameters for :connect , :r etc.