使用 sqlcmd 搭配腳本變數

適用於:SQL ServerAzure SQL 資料庫Azure SQL 受控執行個體Azure Synapse AnalyticsMicrosoft Fabric 中的 SQL 資料庫

sqlcmd 公用程式可讓您輸入 Transact-SQL 語句、系統程式和腳本檔案。

Note

若要找出系統上已安裝哪些 sqlcmd 變體和版本,請參閱 檢查已安裝的 sqlcmd 公用程式版本。 如需如何取得 sqlcmd 的資訊,請參閱 下載並安裝 sqlcmd 公用程式。

在 sqlcmd 中編寫變數腳本

用於指令碼中的變數稱為指令碼變數。 指令碼變數可讓一個指令碼使用於多個狀況中。 例如,如果您想要針對多個伺服器執行一個指令碼,而不針對每個伺服器修改指令碼,您可以使用指令碼變數來代表伺服器名稱。 只要變更提供給指令碼變數的伺服器名稱,相同的指令碼就可以在不同的伺服器上執行。

您可以使用 setvar 命令 明確定義腳本變數,或使用 sqlcmd -v 選項 以隱含方式定義。

本文也包含使用 SET在命令行定義環境變數的範例。

使用 setvar 命令設定指令碼變數

命令 setvar 會定義腳本變數。 使用 setvar 命令定義的變數會儲存在內部。 指令碼變數不應與在命令提示字元中使用 SET 所定義的環境變數產生混淆。 如果腳本參考不是環境變數或未使用 setvar定義的變數,則會傳回錯誤訊息,並停止執行腳本。 如需詳細資訊,請參閱 -b 中的 選項。

變數優先順序 (由低至高)

如果有多個類型的變數具有相同的名稱,會使用具有最高優先順序的變數。

  1. 系統層級環境變數
  2. 使用者層級環境變數
  3. 命令殼層 (SET X=Y) 在啟動 sqlcmd 之前於命令提示字元設定
  4. sqlcmd -v X=Y
  5. :Setvar X Y

Note

若要檢視 Windows 11 上的環境變數,請開啟 [ 設定],然後流覽至 [系統>關於],然後選取 [ 進階系統設定 ] 連結。 在 [系統屬性] 視窗中,選取 [ 環境變數]。 在 Linux 上,在命令列輸入 printenv ,然後在 macOS 中輸入 env。

隱式設定指令碼變數

當您透過含有 sqlcmd 相關變數的選項啟動 sqlcmd 時,會將 sqlcmd 變數隱含設定為使用該選項所指定的值。 在下列範例中, sqlcmd 透過 -l 選項啟動。 這將會隱含地設定 SQLLOGINTIMEOUT 變數。

sqlcmd -l 60

您也可以使用 -v 選項來設定存在於指令碼中的指令碼變數。 在下列指令碼 (檔名為 testscript.sql) 中, ColumnName 為指令碼變數。

USE AdventureWorks2022;

SELECT x.$(ColumnName)
FROM Person.Person x
WHERE x.BusinessEntityID < 5;

您可以接著指定要使用 -v 選項傳回的資料行名稱:

sqlcmd -v ColumnName ="FirstName" -i c:\testscript.sql

若要使用相同的指令碼傳回不同的資料行,請變更 ColumnName 指令碼變數的值。

sqlcmd -v ColumnName ="LastName" -i c:\testscript.sql

腳本變數名稱和值的指南

當您為指令碼變數命名時,請考慮下列指導方針:

  • 變數名稱不能包含空白字元或引號。

  • 變數名稱的格式不能和變數運算式的格式相同,例如 $(var) 。

  • 指令碼變數不區分大小寫。

    Note

    如果未指定任何值給 sqlcmd 環境變數,則會移除該變數。 不使用 :setvar VarName 值即可清除變數。

當您指定指令碼變數的值時,請考慮下列指導方針:

  • 使用 setvar 或 -v 選項定義的變數值,如果字串值包含空格,則必須以引號括住。
  • 如果引號是變數值的一部分,則必須逸出。 例如: :setvar MyVar "spac""e" 。

cmd.exe SET 變數值和名稱準則

使用 SET 所定義的變數是 Cmd.exe 環境的一部分,並且可供 sqlcmd 參考。 請參考下列指引:

  • 變數名稱不能包含空白字元或引號。
  • 變數值可能包含空格或引號。

sqlcmd 指令碼變數

Variable 相關選項 R/W Default
SQLCMDUSER 1 -U R 2 ""
SQLCMDPASSWORD 1 -P -- ""
SQLCMDSERVER 1 -S R 2 "DefaultLocalInstance"
SQLCMDWORKSTATION -H R 2 "ComputerName"
SQLCMDDBNAME -d R 2 ""
SQLCMDLOGINTIMEOUT -l R/W 3 “8”(秒)
SQLCMDSTATTIMEOUT -t R/W 3 "0" = 永遠等候
SQLCMDHEADERS -h R/W 3 "0"
SQLCMDCOLSEP -s R/W 3 " "
SQLCMDCOLWIDTH -w R/W 3 "0"
SQLCMDPACKETSIZE -a R 2 "4096"
SQLCMDERRORLEVEL -m R/W 3 "0"
SQLCMDMAXVARTYPEWIDTH -y R/W 3 "256"
SQLCMDMAXFIXEDTYPEWIDTH -Y R/W 3 "0" = 無限制
SQLCMDEDITOR R/W 3 "edit.com"
SQLCMDINI R 2 ""

1SQLCMDUSER、SQLCMDPASSWORD 和 SQLCMDSERVER 會在使用 :Connect 時設定。

2 R 表示在程式初始化期間只能設定該值一次。

3 R/W 表示可以使用 命令來重設 setvar 值,而後續命令會使用新的值。

Examples

本文中的程式碼範例使用 AdventureWorks2025 或 AdventureWorksDW2025 範例資料庫,您可以從 Azure Data SQL 範例存放庫 GitHub 存放庫下載這些資料庫。

A. 在指令碼中使用 setvar 命令

許多 sqlcmd 選項可以在指令碼中使用 setvar 命令來控制。 下列範例會建立指令碼 test.sql ,其中的 SQLCMDLOGINTIMEOUT 變數設為 60 秒,而另一個指令碼變數 server則設為 testserver。 下列程式碼是在 test.sql中。

:setvar SQLCMDLOGINTIMEOUT 60
:setvar server "testserver"
:connect $(server) -l $(SQLCMDLOGINTIMEOUT)

USE AdventureWorks2022;

SELECT FirstName, LastName
FROM Person.Person;

隨後會使用 sqlcmd 呼叫指令碼:

sqlcmd -i c:\test.sql

B. 以互動方式使用 setvar 命令

下列範例顯示如何使用 setvar 命令,以互動方式設定指令碼變數。

sqlcmd
:setvar MYDATABASE AdventureWorks2022
USE $(MYDATABASE);
GO

結果集如下所示。

Changed database context to 'AdventureWorks2022'
1>

C. 在 sqlcmd 內使用命令提示字元環境變數

在下列範例中,設定了四個環境變數 are ,然後從 sqlcmd 進行呼叫。

SET tablename=Person.Person
SET col1=FirstName
SET col2=LastName
SET title=Ms.
sqlcmd -d AdventureWorks2022
1> SELECT TOP 5 $(col1) + ' ' + $(col2) AS Name
2> FROM $(tablename)
3> WHERE Title ='$(title)'
4> GO

D. 在 sqlcmd 內使用使用者層級環境變數

下列範例在命令提示字元中設定了使用者層級環境變數 %Temp% ,並將其傳遞至 sqlcmd 輸入檔。 若要取得使用者層級環境變數,請在 [控制台] 中按兩下 [系統]。 選取 [進階] 索引標籤,然後選取 [環境變數]。

下列程式碼是在輸入檔 C:\testscript.txt中:

:OUT $(MyTempDirectory)
USE AdventureWorks2022;

SELECT FirstName
FROM AdventureWorks2022.Person.Person
WHERE BusinessEntityID < 5;

下列程式碼是在命令提示字元中輸入的:

SET MyTempDirectory=%Temp%\output.txt
sqlcmd -i C:\testscript.txt

以下結果將被傳送到輸出檔案C:\Documents and Settings\<user>\Local Settings\Temp\output.txt。

Changed database context to 'AdventureWorks2022'.
FirstName
--------------------------------------------------
Gustavo
Catherine
Kim
Humberto

(4 rows affected)

E. 使用啟動指令碼

啟動 sqlcmd 時,會執行 sqlcmd 啟動指令碼。 下列範例會設定環境變數 SQLCMDINI。 這是下者的內容: init.sql.

SET NOCOUNT ON
GO

DECLARE @nt_username nvarchar(128)
SET @nt_username = (SELECT rtrim(convert(nvarchar(128), nt_username))
FROM sys.dm_exec_sessions WHERE spid = @@SPID)
SELECT  @nt_username + ' is connected to ' +
rtrim(CONVERT(nvarchar(20), SERVERPROPERTY('servername'))) +
' (' +`
rtrim(CONVERT(nvarchar(20), SERVERPROPERTY('productversion'))) +
')'
:setvar SQLCMDMAXFIXEDTYPEWIDTH 100
SET NOCOUNT OFF
GO

:setvar SQLCMDMAXFIXEDTYPEWIDTH

這會在 init.sql 啟動時呼叫 sqlcmd 檔案。

SET sqlcmdini=c:\init.sql
sqlcmd

以下是輸出。

1> <user> is connected to <server> (9.00.2047.00)

Note

-X 選項會停用啟動指令碼功能。

F. 可變擴展

下列範例顯示如何以 sqlcmd 變數的形式來使用資料。

USE AdventureWorks2022;
GO
CREATE TABLE AdventureWorks2022.dbo.VariableTest (Col1 NVARCHAR(50));
GO

在 Col1 的 dbo.VariableTest 中插入一個資料列,包含值 $(tablename)。

INSERT INTO AdventureWorks2022.dbo.VariableTest (Col1)
VALUES ('$(tablename)');
GO

在 sqlcmd 提示字元中,當沒有任何變數設定等於 $(tablename) 時,下列陳述式會傳回資料列,同時傳回訊息「'tablename' 指令碼變數未定義」。預設不設定 sqlcmd 旗標 -b。 如果 -b 已設定,則 sqlcmd 會在「未定義變數」錯誤後終止。

sqlcmd
1> SELECT Col1 FROM dbo.VariableTest WHERE Col1 = '$(tablename)';
2> GO
3> SELECT Col1 FROM dbo.VariableTest WHERE Col1 = N'$(tablename)';
4> GO

結果集如下所示。

1> Col1
2> ------------------
3> $(tablename)
4>
5> (1 rows affected)

假使變數 MyVar 設定為 $(tablename)。

6> :setvar MyVar $(tablename)

下列陳述式會傳回該資料列,而且還會傳回訊息「'tablename' 指令碼變數未定義」。

6> SELECT Col1 FROM dbo.VariableTest WHERE Col1 = '$(tablename)';
7> GO

1> SELECT Col1 FROM dbo.VariableTest WHERE Col1 = N'$(tablename)';
2> GO

這些陳述會傳回資料列。

1> SELECT Col1 FROM dbo.VariableTest WHERE Col1 = '$(MyVar)';
2> GO
1> SELECT Col1 FROM dbo.VariableTest WHERE Col1 = N'$(MyVar)';
2> GO