Wie verwende ich eine Variable für den Datenbanknamen in T-SQL?

123

Ich verwende den Datenbanknamen an mehreren Stellen in meinem Skript und möchte ihn schnell ändern können. Deshalb suche ich nach etwas Ähnlichem:

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

Aber es funktioniert nicht. Wie kann man diesen Code richtig schreiben?

Erick Sasse
quelle

Antworten:

134

Fügen Sie das gesamte Skript in eine Vorlagenzeichenfolge mit Platzhaltern {SERVERNAME} ein. Bearbeiten Sie dann die Zeichenfolge mit:

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

und dann ausführen mit

EXECUTE (@SQL_SCRIPT)

Es ist kaum zu glauben, dass im Laufe von drei Jahren niemand bemerkt hat, dass mein Code nicht funktioniert !

Sie können nicht EXECmehrere Chargen. GOist ein Batch-Trennzeichen, keine T-SQL-Anweisung. Es ist notwendig, drei separate Zeichenfolgen zu erstellen und EXECnach der Ersetzung jeweils eine.

Ich nehme an, man könnte etwas "Kluges" tun, indem man die einzelne Vorlagenzeichenfolge durch Aufteilen in mehrere Zeilen aufteilt GO. Ich habe das in ADO.NET-Code gemacht.

Und woher habe ich das Wort "SERVERNAME"?

Hier ist ein Code, den ich gerade getestet habe (und der funktioniert):

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)
John Saunders
quelle
2
+1 Sehr nette Herangehensweise ... Sie haben mich gerade vor einer Menge Arbeit gerettet, danke ... Obwohl es EXECUTE (@SQL_SCRIPT) sein sollte, oder zumindest hat das bei mir funktioniert.
reSPAWNed
2
Ich muss jedoch vorsichtig sein, wenn ich entkomme.
usr
4
SYSNAMEwäre ein geeigneterer Datentyp, als er VARCHAR(255)auch verwenden sollte QUOTENAME, um mit allen möglichen Datenbanknamen umzugehen (und möglicherweise die SQL-Injection abhängig von der Quelle des Namens zu verhindern)
Martin Smith,
1
Funktioniert nicht, wenn ich CREATE SCHEMAin einer anderen Datenbank verwenden möchte USE {DBNAME}. Schema erstellt in falscher Datenbank; /
Bomberlt
103

Sie können hierfür auch den sqlcmdModus verwenden (aktivieren Sie diesen im Menü "Abfrage" in Management Studio).

:setvar dbname "TEST" 

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

BEARBEITEN:

Überprüfen Sie diesen MSDN- Artikel, um Parameter über das SQLCMD-Tool festzulegen.

Martin Smith
quelle
1
Wie kann diese Methode bereits deklarierte Variablen verwenden? Können Sie anstelle von "TEST" einen @dbName hinzufügen? Ich habe versucht und nicht funktioniert
Syclee
1
@syclee Eine TSQL-Variable? Nein, die sqlcmd-Ersetzungen werden ausgeführt, bevor das Skript überhaupt an den Server gesendet wird.
Martin Smith
@ MartinSmith Hey, ich möchte den Datenbanknamen als OUTPUT-Befehl. Wie kann ich es mit SQLCMD haben?
Kunal Kakkad
11

Leider können Sie keine Datenbanknamen mit einer Variablen in diesem Format deklarieren.

Für das, was Sie erreichen möchten, müssen Sie Ihre Anweisungen in eine EXEC () - Anweisung einschließen. Sie hätten also so etwas wie:

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

Dann ruf an

EXECUTE(@Sql) or sp_executesql(@Sql)

um die SQL-Zeichenfolge auszuführen.

Dillie-O
quelle
EXECsucht nach einer gespeicherten Prozedur. In diesem Fall EXECUTEwird benötigt.
Bob Blogge
2
Eigentlich muss ich mich entschuldigen. Es stellt sich heraus EXECund EXECUTEsind die gleichen. Ich gab die Erklärung ab, nachdem ich versagt hatte EXECund Erfolg hatte EXECUTE. Obwohl mein eigentliches Problem offensichtlich auch nichts damit zu tun hatte.
Bob Blogge
2
Mach das nicht in der Produktion ... jemals.
Magic Octopus Urn
@MagicOctopusUrn variieren alten Beitrag und sehr Kommentare, aber ich bin neugierig, warum nicht? sollte es nicht anforderungsspezifisch sein?
Harte
@MagicOctopusUrn Liegt das am Injektionspotential?
Isaac Reefman
5

Sie können keine Variable in einer Anweisung zum Erstellen einer Tabelle verwenden. Das Beste, was ich vorschlagen kann, ist, die gesamte Abfrage als Zeichenfolge zu schreiben und diese auszuführen.

Versuchen Sie so etwas:

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

exec (@query);
Andrew Hare
quelle