Як використовувати змінну для імені бази даних у 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.

І звідки я взяв слово "SERVERNAME"?

Ось код, який я щойно перевірив (і який працює):

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 Дуже приємний підхід ... Ви щойно врятували мене від тонни роботи, thx ... Хоча це повинно бути ВИКОНАННЯ (@SQL_SCRIPT), або принаймні це те, що працювало для мене.
reSPAWNed

2
Потрібно бути обережними з втечею.
usr

4
SYSNAMEбуде більш відповідним типом даних, ніж VARCHAR(255)також слід використовувати QUOTENAMEдля роботи з усіма можливими іменами баз даних (і, можливо, для запобігання ін'єкції SQL залежно від джерела імені)
Мартін Сміт

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

103

Ви також можете використовувати sqlcmdрежим для цього (увімкніть це в меню "Запит" в студії управління).

: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
як цей метод може використовувати вже оголошені змінні? Замість "TEST" можна додати @dbName? Я спробував і не вийшло
syclee

1
@syclee Змінна TSQL? Жодна заміна sqlcmd не проводиться до того, як сценарій навіть буде відправлений на сервер.
Мартін Сміт

@MartinSmith Привіт, я хочу, щоб ім'я db було командою OUTPUT. То як я можу це мати за допомогою SQLCMD.?
Kunal Kakkad

12

На жаль, ви не можете оголосити імена бази даних зі змінною у цьому форматі.

Для того, що ви намагаєтеся зробити, вам знадобиться загорнути свої висловлювання в оператор EXEC (). Отже, у вас вийде щось на кшталт:

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

Тоді дзвоніть

EXECUTE(@Sql) or sp_executesql(@Sql)

виконати рядок sql.


EXECшукає збережену процедуру. У цьому випадку EXECUTEпотрібно.
Боб Блог

2
Насправді мені потрібно вибачитися. Виявляється, EXECі EXECUTEте саме. Я зробив заяву після невдачі EXECта успіху EXECUTE. Хоча явно моя реальна проблема не була пов'язана ні з якою.
Боб Блог

2
Не робіть цього на виробництві ... Ніколи.
Чарівна восьминога урна

@MagicOctopusUrn варіюють старий пост і дуже коментарі, але мені цікаво знаю, чому ні? чи не повинно це бути конкретним вимогою ??
Суворі

@MagicOctopusUrn Це через потенціал для ін'єкцій?
Ісаак Ріфман

5

Ви не можете використовувати змінну в операторі створення таблиці. Найкраще, що я можу запропонувати, - написати весь запит як рядок і виконати це.

Спробуйте щось подібне:

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

exec (@query);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.