外出先で変数を永続化する方法はありますか?
Declare @bob as varchar(50);
Set @bob = 'SweetDB';
GO
USE @bob --- see note below
GO
INSERT INTO @bob.[dbo].[ProjectVersion] ([DB_Name], [Script]) VALUES (@bob,'1.2')
'USE @bob'行については、このSOの質問を参照してください。
外出先で変数を永続化する方法はありますか?
Declare @bob as varchar(50);
Set @bob = 'SweetDB';
GO
USE @bob --- see note below
GO
INSERT INTO @bob.[dbo].[ProjectVersion] ([DB_Name], [Script]) VALUES (@bob,'1.2')
'USE @bob'行については、このSOの質問を参照してください。
回答:
このgo
コマンドは、コードを個別のバッチに分割するために使用されます。それがまさにあなたがやりたいことであるなら、あなたはそれを使うべきです、しかしそれはバッチが実際に別々であり、それらの間で変数を共有することができないことを意味します。
あなたの場合、解決策は簡単です。go
ステートメントを削除するだけで、そのコードでは必要ありません。
補足:use
ステートメントで変数を使用することはできません。変数はデータベースの名前である必要があります。
go
コマンドは、コードを個別のバッチに分割するために使用されます。それがあなたのやりたいことなら、それを使うべきですが、それはバッチが実際には別々であり、それらの間で変数を共有できないことを意味します。
一時テーブルを使用します。
CREATE TABLE #variables
(
VarName VARCHAR(20) PRIMARY KEY,
Value VARCHAR(255)
)
GO
Insert into #variables Select 'Bob', 'SweetDB'
GO
Select Value From #variables Where VarName = 'Bob'
GO
DROP TABLE #variables
go
私はこの質問からのこの答え を好むGOのグローバル変数
これには、元々やりたかったこともできるという追加の利点があります。
注意点は、SQLCMDモードをオンにする([クエリ]-> [SQLCMD]の下)か、すべてのクエリウィンドウでデフォルトでオンにする必要があることです([ツール]-> [オプション]、[クエリ結果]-> [デフォルト]、SQLCMDモードで新しいクエリを開きます)。
次に、次のタイプのコードを使用できます(Oscar E. Fraxedas Tormoによる同じ回答から完全に削除されました)
--Declare the variable
:setvar MYDATABASE master
--Use the variable
USE $(MYDATABASE);
SELECT * FROM [dbo].[refresh_indexes]
GO
--Use again after a GO
SELECT * from $(MYDATABASE).[dbo].[refresh_indexes];
GO
SQL Serverを使用している場合は、次のようにスクリプト全体のグローバル変数を設定できます。
:setvar sourceDB "lalalallalal"
後でスクリプトで次のように使用します。
$(sourceDB)
Server Managment StudiでSQLCMDモードがオンになっていることを確認します。これは、トップメニューの[クエリ]をクリックして、SQLCMDモードをオンに切り替えます。
トピックの詳細については、こちらをご覧ください: MSドキュメント
これが役立つかどうかわからない
declare @s varchar(50)
set @s='Northwind'
declare @t nvarchar(100)
set @t = 'select * from ' + @s + '.[dbo].[Customers]'
execute sp_executesql @t
一時テーブルはGOステートメントで保持されるため、...
SELECT 'value1' as variable1, 'mydatabasename' as DbName INTO #TMP
-- get a variable from the temp table
DECLARE @dbName VARCHAR(10) = (select top 1 #TMP.DbName from #TMP)
EXEC ('USE ' + @dbName)
GO
-- get another variable from the temp table
DECLARE @value1 VARCHAR(10) = (select top 1 #TMP.variable1 from #TMP)
DROP TABLE #TMP
きれいではありませんが、機能します
一時テーブルに保存/ロードする独自のストアドプロシージャを作成します。
MyVariableSave -- Saves variable to temporary table.
MyVariableLoad -- Loads variable from temporary table.
次に、これを使用できます。
print('Test stored procedures for load/save of variables across GO statements:')
declare @MyVariable int = 42
exec dbo.MyVariableSave @Name = 'test', @Value=@MyVariable
print(' - Set @MyVariable = ' + CAST(@MyVariable AS VARCHAR(100)))
print(' - GO statement resets all variables')
GO -- This resets all variables including @MyVariable
declare @MyVariable int
exec dbo.MyVariableLoad 'test', @MyVariable output
print(' - Get @MyVariable = ' + CAST(@MyVariable AS VARCHAR(100)))
出力:
Test stored procedures for load/save of variables across GO statements:
- Set @MyVariable = 42
- GO statement resets all variables
- Get @MyVariable = 42
これらも使用できます。
exec dbo.MyVariableList -- Lists all variables in the temporary table.
exec dbo.MyVariableDeleteAll -- Deletes all variables in the temporary table.
の出力exec dbo.MyVariableList
:
Name Value
test 42
テーブル内のすべての変数をリストできることは、実際には非常に便利であることがわかりました。したがって、後で変数をロードしなくても、すべてを1か所で確認するためのデバッグ目的に最適です。
これは##
プレフィックス付きの一時テーブルを使用するため、GOステートメントを存続させるのに十分です。これは、単一のスクリプト内で使用することを目的としています。
そしてストアドプロシージャ:
-- Stored procedure to save a variable to a temp table.
CREATE OR ALTER PROCEDURE MyVariableSave
@Name varchar(255),
@Value varchar(MAX)
WITH EXECUTE AS CALLER
AS
BEGIN
SET NOCOUNT ON
IF NOT EXISTS (select TOP 1 * from tempdb.sys.objects where name = '##VariableLoadSave')
BEGIN
DROP TABLE IF EXISTS ##VariableLoadSave
CREATE TABLE ##VariableLoadSave
(
Name varchar(255),
Value varchar(MAX)
)
END
UPDATE ##VariableLoadSave SET Value=@Value WHERE Name=@Name
IF @@ROWCOUNT = 0
INSERT INTO ##VariableLoadSave SELECT @Name, @Value
END
GO
-- Stored procedure to load a variable from a temp table.
CREATE OR ALTER PROCEDURE MyVariableLoad
@Name varchar(255),
@Value varchar(MAX) OUT
WITH EXECUTE AS CALLER
AS
BEGIN
IF EXISTS (select TOP 1 * from tempdb.sys.objects where name = '##VariableLoadSave')
BEGIN
IF NOT EXISTS(SELECT TOP 1 * FROM ##VariableLoadSave WHERE Name=@Name)
BEGIN
declare @ErrorMessage1 as varchar(200) = 'Error: cannot find saved variable to load: ' + @Name
raiserror(@ErrorMessage1, 20, -1) with log
END
SELECT @Value=CAST(Value AS varchar(MAX)) FROM ##VariableLoadSave
WHERE Name=@Name
END
ELSE
BEGIN
declare @ErrorMessage2 as varchar(200) = 'Error: cannot find saved variable to load: ' + @Name
raiserror(@ErrorMessage2, 20, -1) with log
END
END
GO
-- Stored procedure to list all saved variables.
CREATE OR ALTER PROCEDURE MyVariableList
WITH EXECUTE AS CALLER
AS
BEGIN
IF EXISTS (select TOP 1 * from tempdb.sys.objects where name = '##VariableLoadSave')
BEGIN
SELECT * FROM ##VariableLoadSave
ORDER BY Name
END
END
GO
-- Stored procedure to delete all saved variables.
CREATE OR ALTER PROCEDURE MyVariableDeleteAll
WITH EXECUTE AS CALLER
AS
BEGIN
DROP TABLE IF EXISTS ##VariableLoadSave
CREATE TABLE ##VariableLoadSave
(
Name varchar(255),
Value varchar(MAX)
)
END
バイナリのyes / noが必要な場合(列が存在する場合など)はSET NOEXEC ON
、ステートメントの実行を無効にするために使用できます。 SET NOEXEC ON
GO全体(バッチ全体)で機能します。しかし、上のEXEC背を向けることを忘れないでSET NOEXEC OFF
、スクリプトの終わりに。
IF COL_LENGTH('StuffTable', 'EnableGA') IS NOT NULL
SET NOEXEC ON -- script will not do anything when column already exists
ALTER TABLE dbo.StuffTable ADD EnableGA BIT NOT NULL CONSTRAINT DF_StuffTable_EnableGA DEFAULT(0)
ALTER TABLE dbo.StuffTable SET (LOCK_ESCALATION = TABLE)
GO
UPDATE dbo.StuffTable SET EnableGA = 1 WHERE StuffUrl IS NOT NULL
GO
SET NOEXEC OFF
これはステートメントをコンパイルしますが、それらを実行しません。したがって、存在しないスキーマを参照すると、「コンパイルエラー」が発生します。したがって、スクリプトの2回目の実行(私が行っていること)を「オフ」にすることはできますが、1回目の実行でスクリプトの一部をオフにすることはできません。これは、そうでない列またはテーブルを参照するとコンパイルエラーが発生するためです。まだ存在していません。
以下の手順に従って、NOEXECを利用できます。
テーブルを作成する
#temp_procedure_version(procedure_version varchar(5),pointer varchar(20))
プロシージャのバージョンとバージョンへのポインタを一時テーブルに挿入します #temp_procedure_version
--exampleprocedure_versionポインタ
temp_procedure_version
値に挿入(1.0、 '最初のバージョン')
temp_procedure_version
値に挿入(2.0、 '最終バージョン')
次に、プロシージャのバージョンを取得します。次のステートメントのようにwhere条件を使用できます。
どこ@ProcedureVersion=ProcedureVersion
から選択#temp_procedure_version
する
pointer='first version'
IF (@ProcedureVersion='1.0')
BEGIN
SET NOEXEC OFF --code execution on
END
ELSE
BEGIN
SET NOEXEC ON --code execution off
END
-ここにプロシージャバージョン1.0を挿入します
プロシージャバージョン1.0を....として作成します。
SET NOEXEC OFF -- execution is ON
ここ@ProcedureVersion=ProcedureVersion
から選択#temp_procedure_version
pointer = '最終バージョン'
IF (@ProcedureVersion='2.0')
BEGIN
SET NOEXEC OFF --code execution on
END
ELSE
BEGIN
SET NOEXEC ON --code execution off
END
プロシージャバージョン2.0を次のように作成します。
SET NOEXEC OFF -- execution is ON
-一時テーブルを削除します
ドロップテーブル #temp_procedure_version