web-dev-qa-db-ja.com

SSMSのSQLCMDモードと@@ variable展開

(コマンドラインからではなく)SSMSでSQLCMDモードを使用する場合、現在のサーバーとインスタンスを変数に割り当てる方法はありますか?これは、通常のTSQL変数の割り当てとは異なります。

問題の定義

SQLCMDの変数拡張機能を使用して、導入した既存のtsql文字列構築マッシュの代わりに、配置スクリプトの環境固有の値を置き換えたいと思います。現在の環境を除いて、デプロイを処理するためのSQLCMDの使用は非常にうまく進んでいます。

--
-- define 2 sqlcmd variables that will be expanded in scripts
--
:setvar dbServer "DEVA2\DEV2"
:setvar dbNotServer @@servername

SELECT
    '$(dbServer)' AS hard_coded_value
,   @@servername AS [servername]
,   '$(dbNotServer)' AS dbNotServer

そして、それは以下の結果を生成します。

hard_coded_value  servername  dbNotServer
DEVA2\DEV2        DEVA2\DEV2  @@servername

ミートローフは のうち2は悪くない と言いますが、私はむしろ3から3の解決策を持っています。スクリプトがテストサーバーに展開されたとき、スクリプトの編集は展開担当者に任せたくありません。

SQLCMDを使用する唯一の解決策がコマンドラインからスクリプトを完全に呼び出すことである場合、それを受け入れることができますが、SQLCMDを使用するのは環境に優しいので、ここでこれを破棄したいと思います。

望ましい出力

:setvar dbNotServer @@servername
SELECT '$(dbNotServer)' AS worked

結果

worked
DEVA\DEV2

実りのない追求

最初のBOLリンクは約束を示しました。私がしなければならなかったのはSQLCMDSERVERを使用することだけでしたが、役に立ちませんでした。 SQLSMSモードでSSMSのコンテキスト内で実行すると、致命的なスクリプトエラーがスローされます

-- A fatal scripting error occurred.
-- Variable SQLCMDSERVER is not defined.
SELECT '$(SQLCMDSERVER)' AS [FatalScriptingError]

タンブルウィード更新

2011-08-12回答に基づいて、問題を最も単純な形に減らすために、クエリを単純化しすぎました(私の謝罪)。使用したクエリの一部を以下に示します。 2つのレスポンダは、@@ servernameをティックマークでラップすると結果としてリテラル値が得られ、拡張された値を取得するには、引用符からアンラップする必要があります。私の望みは、アンラップを伴う文字列の構築ではなく、sqlcmd変数置換を使用することでした。

INSERT INTO
    dbo.SSISCONFIG
(
    ConfigurationFilter
,   ConfiguredValue
,   PackagePath
,   ConfiguredValueType
,   Application
,   Category
,   Subcategory
,   Comment
)
SELECT
    'Default.Accounting' AS ConfigurationFilter
,   'Data Source=$(dbServer);Initial Catalog=Accounting;Provider=SQLNCLI10.1;Integrated Security=SSPI;Packet Size=32767;' AS ConfiguredValue
,   '\Package.Connections[Accounting].Properties[ConnectionString]' AS PackagePath
,   'String' AS ConfiguredValueType
,   'Defaults' AS Application
,   'Connection' AS Category
,   'Database' AS Subcategory
,   'Default connection string' AS Comment
SELECT
    'Default.$(sqlVersion).CorporateReporting' AS ConfigurationFilter
,   'Data Source=$(dwServer);Initial Catalog=CRDS;Provider=SQLNCLI10.1;Integrated Security=SSPI;Packet Size=32767;' AS ConfiguredValue
,   '\Package.Connections[CorporateReporting].Properties[ConnectionString]' AS PackagePath
,   'String' AS ConfiguredValueType
,   'Defaults' AS Application
,   'Connection' AS Category
,   'Database' AS Subcategory
,   'Default connection string' AS Comment

コマンドライン呼び出しは(期待どおりに)機能します

C:\>sqlcmd -E -d master -S DEVA2\DEV2 -Q "SELECT '$(SQLCMDSERVER)' AS [servername]"

SQLCMD変数に格納されているデータベース変数の評価値を取得するために、:setvar x @@ servernameの他の順列を試行して破棄しました。この時点で、クエリのコンパイル前にsqlcmd変数がクエリで代替されていることはほぼ確実ですが、間違っていることが証明されることを望んでいます。

BOLリファレンス

8
billinkc

私が何かを逃していない限り、アポストロフィなしでこれはうまくいきませんか?:

:setvar dbNotServer @@servername
SELECT $(dbNotServer) AS worked

SSMSを介してSQLCMDモードでSERVER\INSTANCEを返します。

2018年12月12日編集別の質問に対する私の答えに出会い、確認した後、私は問題を見ることができます、それはこれに要約すると信じています:

:setvar dbNotServer @@servername
print '$(dbNotServer)'

これは@@ servernameを出力し、必要な出力は@@ servernameの値です。私がこれを行うために見た唯一の方法は、受け入れられた答え here にあります

3
SqlACID

SQL-CMD変数は、バッチが実行される前に評価されます。したがって、t-sql変数の値をCMD変数に割り当てることはできません。

3
Stefan Wilms

「必要な出力」の下で、サーバーに送信されるT-SQLは次のようになります。

SELECT '@@servername' AS worked

@@servernameを単一引用符で囲むと、文字列リテラルになり、実際の名前に置き換えられません。そのため、@@servernameが値として表示されます。

サーバー名を表示する場合は、単一引用符を削除して、T-SQLを作成します。

SELECT @@servername AS worked

私は質問を理解していることは完全には明らかではありませんが、これが「望ましい出力」の内容を取得する方法です。

1
Pavel