Как использовать переменную для имени базы данных в T-SQL?


123

Я использую имя базы данных в нескольких местах в моем скрипте, и я хочу иметь возможность быстро его изменить, поэтому я ищу что-то вроде этого:

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

Но не работает. Итак, как правильно написать этот код?

Ответы:


135

Поместите весь сценарий в строку шаблона с заполнителями {SERVERNAME}. Затем отредактируйте строку, используя:

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

а затем запустите его с помощью

EXECUTE (@SQL_SCRIPT)

Трудно поверить, что за три года никто не заметил, что мой код не работает !

Вы не можете EXECнесколько партий. GOявляется разделителем пакетов, а не оператором T-SQL. Необходимо построить три отдельные строки, а затем EXECкаждой после подстановки.

Я полагаю, можно было бы сделать что-нибудь «умное», разбив одну строку шаблона на несколько строк, разделив на GO; Я сделал это в коде ADO.NET.

А откуда у меня слово "ИМЯ СЕРВЕРА"?

Вот код, который я только что протестировал (и который работает):

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 Очень хороший подход ... Вы только что избавили меня от тонны работы, спасибо ... Хотя должен быть EXECUTE (@SQL_SCRIPT), или, по крайней мере, у меня это сработало.
обновлено

2
Однако нужно быть осторожным с побегом.
usr

4
SYSNAMEбыл бы более подходящим типом данных, чем VARCHAR(255)также следует использовать QUOTENAMEдля работы со всеми возможными именами баз данных (и, возможно, для предотвращения SQL-инъекций в зависимости от источника имени)
Мартин Смит,

1
Не работает, если я хочу использовать CREATE SCHEMAдругую базу данных USE {DBNAME}. Схема создается в неправильной базе данных; /
Bomberlt

103

Вы также можете использовать sqlcmdдля этого режим (включите его в меню «Запрос» в Management Studio).

:setvar dbname "TEST" 

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

РЕДАКТИРОВАТЬ:

Ознакомьтесь с этой статьей MSDN, чтобы установить параметры с помощью инструмента SQLCMD.


1
как этот метод может использовать уже объявленные переменные? Можно ли вместо "ТЕСТ" добавить @dbName? Я пробовал и не работал
syclee

1
@syclee Переменная TSQL? Никакие подстановки sqlcmd не выполняются до того, как сценарий будет отправлен на сервер.
Мартин Смит,

@MartinSmith Эй, я хочу, чтобы имя базы данных было командой ВЫВОДА. Итак, как я могу получить это с помощью SQLCMD?
Кунал Каккад

12

К сожалению, вы не можете объявить имена баз данных с помощью переменной в этом формате.

Для того, что вы пытаетесь выполнить, вам нужно будет заключить свои операторы в оператор EXEC (). Итак, у вас будет что-то вроде:

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

Тогда позвони

EXECUTE(@Sql) or sp_executesql(@Sql)

для выполнения строки sql.


EXECищет хранимую процедуру. В этом случае EXECUTEэто необходимо.
Боб Блогг

2
На самом деле мне нужно извиниться. Оказывается EXECи EXECUTEтакие же. Я сделал заявление после того, как потерпел неудачу EXECи преуспел в этом EXECUTE. Хотя очевидно, что моя настоящая проблема ни с одним из них не связана.
Боб Блогге

2
Не делайте этого в производстве ... Никогда.
Magic Octopus Urn

@MagicOctopusUrn меняет старый пост и очень комментарии, но мне любопытно, почему бы и нет? Разве это не должно быть конкретным требованием ??
Harsh

@MagicOctopusUrn Это из-за возможности инъекции?
Исаак Рифман

5

Вы не можете использовать переменную в операторе создания таблицы. Лучшее, что я могу предложить, - это написать весь запрос в виде строки и выполнить ее.

Попробуйте что-то вроде этого:

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

exec (@query);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.