Existe uma maneira de manter uma variável através de uma vez?
-
06-09-2019 - |
Pergunta
Existe uma maneira de manter uma variável através de uma vez?
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')
Veja este SO pergunta para a linha 'USE @bob'.
Solução
O comando go
é usado para dividir código em lotes separados. Se isso é exatamente o que você quer fazer, então você deve usá-lo, mas isso significa que os lotes são realmente separado, e você não pode variáveis ??partilhar entre eles.
No seu caso, a solução é simples; você pode simplesmente remover as instruções go
, eles não são necessários nesse código.
Nota lateral:. Você não pode usar uma variável em um comunicado use
, ele tem de ser o nome de um banco de dados
Outras dicas
Use uma tabela temporária:
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
Eu prefiro o esta resposta desta questão variáveis ??globais com GO
O que tem a vantagem adicional de ser capaz de fazer o que você queria, a fazer tão bem.
A ressalva é que você precisa para ativar o modo SQLCMD (sob query-> SQLCMD) ou ligá-lo por padrão para todas as janelas de consulta (Ferramentas-> Opções, em seguida, consulta Resultados-> Por padrão, abrem novas consultas no modo SQLCMD )
Em seguida, você pode usar o seguinte tipo de código (completamente rasgado daquela mesma resposta por 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
Não tenho certeza, se isso ajuda
declare @s varchar(50)
set @s='Northwind'
declare @t nvarchar(100)
set @t = 'select * from ' + @s + '.[dbo].[Customers]'
execute sp_executesql @t
Se você estiver usando SQL Server, você pode configurar variáveis ??globais para scripts inteiros como:
:setvar sourceDB "lalalallalal"
e posterior utilização no script como:
$(sourceDB)
Faça o modo SQLCMD certeza está em no Server Managment Studi, você pode fazer isso através do menu superior, clique consulta e de alternância Modo SQLCMD diante.
Mais sobre o tema pode ser encontrada aqui: Documentação MS
tabelas temporárias são mantidas ao longo declarações ir, então ...
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
Não é bonito, mas funciona
Crie seus próprios procedimentos armazenados que salvar / carga para uma tabela temporária.
MyVariableSave -- Saves variable to temporary table.
MyVariableLoad -- Loads variable from temporary table.
Em seguida, você pode usar isto:
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)))
Output:
Test stored procedures for load/save of variables across GO statements:
- Set @MyVariable = 42
- GO statement resets all variables
- Get @MyVariable = 42
Você também pode usar estes:
exec dbo.MyVariableList -- Lists all variables in the temporary table.
exec dbo.MyVariableDeleteAll -- Deletes all variables in the temporary table.
Saída de exec dbo.MyVariableList
:
Name Value
test 42
Acontece que ser capaz de listar todas as variáveis ??em uma tabela é realmente muito útil. Assim, mesmo se você não carregar uma variável mais tarde, a sua grande para fins de depuração para ver tudo em um só lugar.
Isto usa uma tabela temporária com um prefixo ##
, por isso é apenas o suficiente para sobreviver a uma declaração GO. Pretende-se para ser usado dentro de um único script.
e os procedimentos armazenados:
-- 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
Se você só precisa de um sim binárias / não (como se existe uma coluna), então você pode usar SET NOEXEC ON
para desativar a execução de instruções. obras SET NOEXEC ON
todo GO (em toda a lotes). Mas lembre-se de transformar EXEC para trás em com SET NOEXEC OFF
no final do script.
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
Isso compila declarações, mas não executá-los. Então, você ainda vai ter "erros de compilação" se você faz referência esquema que não existe. Por isso, trabalha para "desligar" o script segundo prazo (o que estou fazendo), mas não funciona para desligar partes do script em 1º de prazo, porque você ainda vai receber erros de compilação se referenciar colunas ou tabelas que don 't ainda existe.