2009-04-07 7 views
107

J'utilise le nom de la base de données en plusieurs endroits dans mon script, et je veux être en mesure de changer rapidement, donc je suis à la recherche de quelque chose comme ceci:Comment utiliser une variable pour le nom de la base de données dans T-SQL?

DECLARE @DBNAME VARCHAR(50) 
SET @DBNAME = 'TEST' 

CREATE DATABASE @DBNAME 
GO 
ALTER DATABASE @DBNAME SET COMPATIBILITY_LEVEL = 90 
GO 
ALTER DATABASE @DBNAME SET RECOVERY SIMPLE 
GO 

Mais il ne fonctionne pas. Alors, quelle est la bonne façon d'écrire ce code?

+0

Dynamic SQL ..... –

Répondre

114

Placez le script entier dans une chaîne de modèle, avec des espaces réservés {SERVERNAME}. Ensuite, modifier la chaîne en utilisant:

SET @SQL_SCRIPT = REPLACE(@TEMPLATE, '{SERVERNAME}', @DBNAME) 

puis l'exécuter avec

EXECUTE (@SQL_SCRIPT) 

Il est difficile de croire que, au cours de trois ans, personne n'a remarqué que mon code ne travail! Vous ne pouvez pas EXEC plusieurs lots. GO est un séparateur de lots, pas une instruction T-SQL. Il est nécessaire de construire trois chaînes séparées, puis de EXEC chacune après substitution.

Je suppose que l'on pourrait faire quelque chose de "malin" en cassant la chaîne de template unique en plusieurs lignes en divisant GO; J'ai fait cela dans le code ADO.NET.

Et d'où vient le mot "SERVERNAME"?

est ici un code que je viens de tester (et qui fonctionne):

DECLARE @DBNAME VARCHAR(255) 
SET @DBNAME = 'TestDB' 

DECLARE @CREATE_TEMPLATE VARCHAR(MAX) 
DECLARE @COMPAT_TEMPLATE VARCHAR(MAX) 
DECLARE @RECOVERY_TEMPLATE VARCHAR(MAX) 

SET @CREATE_TEMPLATE = 'CREATE DATABASE {DBNAME}' 
SET @COMPAT_TEMPLATE='ALTER DATABASE {DBNAME} SET COMPATIBILITY_LEVEL = 90' 
SET @RECOVERY_TEMPLATE='ALTER DATABASE {DBNAME} SET RECOVERY SIMPLE' 

DECLARE @SQL_SCRIPT VARCHAR(MAX) 

SET @SQL_SCRIPT = REPLACE(@CREATE_TEMPLATE, '{DBNAME}', @DBNAME) 
EXECUTE (@SQL_SCRIPT) 

SET @SQL_SCRIPT = REPLACE(@COMPAT_TEMPLATE, '{DBNAME}', @DBNAME) 
EXECUTE (@SQL_SCRIPT) 

SET @SQL_SCRIPT = REPLACE(@RECOVERY_TEMPLATE, '{DBNAME}', @DBNAME) 
EXECUTE (@SQL_SCRIPT) 
+2

+1 Très belle approche ... Vous venez de me sauver d'une tonne de travail, thx ... Bien qu'il devrait être EXECUTE (@SQL_SCRIPT), ou du moins c'est ce qui a fonctionné pour moi. – reSPAWNed

+2

Il faut faire attention à s'échapper, cependant. – usr

+4

'SYSNAME' serait un type de données plus approprié que' VARCHAR (255) 'devrait également utiliser' QUOTENAME' pour traiter tous les noms de bases de données possibles (et éventuellement empêcher l'injection SQL selon la source du nom) –

5

Vous ne pouvez pas utiliser une variable dans une instruction create table. La meilleure chose que je puisse suggérer est d'écrire toute la requête sous forme de chaîne et d'exec.

Essayez quelque chose comme ceci:

declare @query varchar(max); 
set @query = 'create database TEST...'; 

exec (@query); 
9

Malheureusement, vous ne pouvez pas déclarer les noms de base de données avec une variable dans ce format. Pour ce que vous essayez d'accomplir, vous aurez besoin d'envelopper vos instructions dans une instruction EXEC(). Donc, vous auriez quelque chose comme:

DECLARE @Sql varchar(max) ='CREATE DATABASE ' + @DBNAME 

appellent alors

EXECUTE(@Sql) or sp_executesql(@Sql) 

pour exécuter la chaîne SQL.

+0

'EXEC' recherche une procédure stockée. Dans ce cas, "EXECUTE" est nécessaire. –

+0

Merci @BobBlogge - Je l'ai mis à jour. –

+2

En fait, je dois m'excuser. Il s'avère que 'EXEC' et' EXECUTE' sont les mêmes. J'ai fait la déclaration après avoir échoué avec 'EXEC' et réussi avec' EXECUTE'. Bien que de toute évidence mon vrai problème n'avait aucun rapport avec l'un ou l'autre. –

90

Vous pouvez également utiliser le mode sqlcmd pour cela (activer ce dans le menu "Requête" dans Management Studio).

:setvar dbname "TEST" 

CREATE DATABASE $(dbname) 
GO 
ALTER DATABASE $(dbname) SET COMPATIBILITY_LEVEL = 90 
GO 
ALTER DATABASE $(dbname) SET RECOVERY SIMPLE 
GO 

EDIT:

Vérifiez cet article MSDN pour définir les paramètres via l'outil SQLCMD.

+0

comment cette méthode peut-elle utiliser des variables déjà déclarées? Au lieu de "TEST" pouvez-vous ajouter un @dbName? J'ai essayé et n'ai pas fonctionné – syclee

+1

@syclee Une variable TSQL? Non, les substitutions sqlcmd sont effectuées avant même que le script ne soit envoyé au serveur. –

+0

@MartinSmith Hey, je veux le nom de DB comme une commande OUTPUT. Alors, comment puis-je l'utiliser en utilisant SQLCMD.? –

Questions connexes