web-dev-qa-db-fra.com

Est-il possible de conserver une variable d'un coup?

Est-il possible de conserver une variable d'un coup?

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')

Voir cette question SO pour la ligne 'USE @bob'.

64
NitroxDM

La commande go permet de scinder le code en lots séparés. Si c'est exactement ce que vous voulez faire, vous devriez l'utiliser, mais cela signifie que les lots sont en réalité séparés et que vous ne pouvez pas partager de variables entre eux.

Dans votre cas, la solution est simple. vous pouvez simplement supprimer les instructions go, elles ne sont pas nécessaires dans ce code.

Note latérale: Vous ne pouvez pas utiliser une variable dans une instruction use, il doit s'agir du nom d'une base de données.

27
Guffa

Utilisez une table temporaire:

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
97
RBarryYoung

Je préfère la this réponse de cette question Global Variables with GO

Ce qui présente l’avantage supplémentaire de pouvoir faire ce que vous vouliez faire au départ.

L'avertissement est que vous devez activer le mode SQLCMD (sous Query-> SQLCMD) ou l'activer par défaut pour toutes les fenêtres de requête (Outils-> Options puis Query Results-> Par défaut, ouvrir de nouvelles requêtes en mode SQLCMD)

Ensuite, vous pouvez utiliser le type de code suivant (complètement arraché de la même réponse par 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
12
Matt Vukomanovic

vous pouvez utiliser SQL dynamique, soyez simplement conscient des risques de sécurité (pas à 100% sur le bon syntex)

déclarer @bob nvarchar (50)

declare @sql nvarchar(max)
set @bob='SweetDB'
set @sql = 'Use ' + @bob

execute sp_executesql @sql
2
DForck42

Si vous utilisez SQL Server, vous pouvez configurer des variables globales pour des scripts complets tels que:

:setvar sourceDB "lalalallalal"

et utiliser plus tard dans le script comme: 

$(sourceDB)

Assurez-vous que le mode SQLCMD est activé dans Server Managment Studi. Vous pouvez le faire via le menu principal. Cliquez sur Requête et activez le mode SQLCMD.

Plus d'informations sur le sujet peuvent être trouvés ici: Documentation MS

1
DanteTheSmith

Pas sûr, si cela aide

declare @s varchar(50)
set @s='Northwind'

declare @t nvarchar(100)
set @t = 'select * from ' + @s + '.[dbo].[Customers]'

execute sp_executesql @t
1
shahkalpesh

Si vous avez juste besoin d'un oui/non binaire (comme s'il y avait une colonne), vous pouvez utiliser SET NOEXEC ON pour désactiver l'exécution des instructions. SET NOEXEC ON fonctionne sur GO (sur plusieurs lots). Mais n'oubliez pas de réactiver EXEC avec SET NOEXEC OFF à la fin du 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

Cela compile les instructions mais ne les exécute pas. Donc, vous aurez toujours des "erreurs de compilation" si vous référencez un schéma qui n'existe pas. Cela fonctionne donc pour "désactiver" le script 2ème exécution (ce que je fais), mais ne permet pas de désactiver des parties du script lors de la première exécution, car vous aurez toujours des erreurs de compilation si vous faites référence à des colonnes ou des tables n'existe pas encore.

0
yzorg

Les tables temporaires sont conservées sur les instructions GO, donc ...

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

Ce n'est pas joli, mais ça marche

0
Remco Nonhebel

Créez vos propres procédures stockées qui sauvegardent/chargent dans une table temporaire.

MyVariableSave   -- Saves variable to temporary table. 
MyVariableLoad   -- Loads variable from temporary table.

Ensuite, vous pouvez utiliser ceci:

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)))

Sortie:

Test stored procedures for load/save of variables across GO statements:
  - Set @MyVariable = 42
  - GO statement resets all variables
  - Get @MyVariable = 42

Vous pouvez également utiliser ceux-ci:

exec dbo.MyVariableList       -- Lists all variables in the temporary table.
exec dbo.MyVariableDeleteAll  -- Deletes all variables in the temporary table.

Sortie de exec dbo.MyVariableList:

Name    Value
test    42

En fait, il est très utile de pouvoir répertorier toutes les variables d’un tableau. Ainsi, même si vous ne chargez pas une variable plus tard, il est très utile, à des fins de débogage, de tout voir au même endroit.

Ceci utilise une table temporaire avec un préfixe ##, il suffit donc de survivre à une instruction GO. Il est destiné à être utilisé dans un seul script.

Et les procédures stockées:

-- 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
0
Contango