2009-04-07 16 views
107

uso el nombre de base de datos en varios lugares en mi guión, y yo quiero ser capaz de cambiar rápidamente, así que estoy buscando algo como esto:¿Cómo usar una variable para el nombre de la base de datos en 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 

Pero no funciona. Entonces, ¿cuál es la forma correcta de escribir este código?

+0

SQL dinámico ..... –

Respuesta

114

Coloque toda la secuencia de comandos en una cadena de plantilla, con marcadores de posición {SERVERNAME}. A continuación, edite la cadena usando:

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

y luego ejecutarlo con

EXECUTE (@SQL_SCRIPT) 

Es difícil de creer que, en el transcurso de tres años, nadie se dio cuenta de que mi código no lo hace trabajo!

No puede EXEC varios lotes. GO es un separador de lotes, no una declaración de T-SQL. Es necesario construir tres cadenas separadas, y luego a EXEC cada una después de la sustitución.

Supongo que se podría hacer algo "inteligente" al dividir la cadena de plantilla simple en varias filas dividiendo en GO; Lo hice en código ADO.NET.

¿Y de dónde saqué la palabra "SERVERNAME"?

Aquí hay un código que Acabo de prueba (y que funciona):

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 Muy buen enfoque ... Acabas de salvarme de una tonelada de trabajo, gracias ... Aunque debería ser EXECUTE (@SQL_SCRIPT), o al menos eso es lo que funcionó para mí. – reSPAWNed

+2

Sin embargo, debes tener cuidado con escapar. – usr

+4

'SYSNAME' sería un tipo de datos más apropiado que' VARCHAR (255) 'también debería usar' QUOTENAME' para tratar con todos los nombres de bases de datos posibles (y posiblemente para evitar la inyección SQL según el origen del nombre) –

5

No puede usar una variable en una declaración create table. Lo mejor que puedo sugerir es escribir toda la consulta como una cadena y ejecutarla.

intentar algo como esto:

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

exec (@query); 
9

Por desgracia no se puede declarar los nombres de bases de datos con una variable en ese formato.

Para lo que está tratando de lograr, tendrá que envolver sus declaraciones dentro de una declaración EXEC(). Por lo que tendría algo como:

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

luego llamar a

EXECUTE(@Sql) or sp_executesql(@Sql) 

para ejecutar la cadena SQL.

+0

'EXEC' busca un procedimiento almacenado. En este caso, se necesita 'EJECUTAR'. –

+0

Gracias @BobBlogge - Lo he actualizado. –

+2

En realidad, necesito disculparme. Resulta que 'EXEC' y' EXECUTE' son lo mismo. Hice la declaración después de fallar con 'EXEC' y tener éxito con' EXECUTE'. Aunque obviamente mi problema real no estaba relacionado con ninguno de los dos. –

90

También puede utilizar el modo sqlcmd para este (habilitar esto en el menú "Consulta" en 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:

Marque esta MSDN artículo para establecer parámetros a través de la herramienta SQLCMD.

+0

¿cómo puede este método usar variables ya declaradas? En lugar de "PRUEBA", ¿puede agregar un @dbName? Intenté y no funcionó – syclee

+1

@syclee ¿Una variable de TSQL? No, las sustituciones sqlcmd se llevan a cabo antes de que el script se envíe al servidor. –

+0

@MartinSmith Oye, quiero el nombre db como un comando OUTPUT. Entonces, ¿cómo puedo tenerlo usando SQLCMD? –

Cuestiones relacionadas