#sql #sql-server #sql-server-2008
#sql #sql-server #sql-server-2008
Вопрос:
Используя SQL Server 2008, я пытаюсь создать строку и выполнить ее с помощью sp_executesql. Очевидно, что некоторые кавычки у меня неправильные. Похоже, что он запускается, но база данных не удалена. Кто-нибудь может мне помочь исправить синтаксис?
USE [master]
GO
DECLARE @sql NVARCHAR(500)
SET @sql = N' IF EXISTS (SELECT NAME FROM master.sys.databases sd where name =''@DBName'')
BEGIN
ALTER DATABASE [@DBName] SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE [@DBName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DROP DATABASE [@DBName]
END';
EXECUTE sp_executesql @sql, N'@DBName sysname', @DBName = 'ReapirInformation'
GO
Я пробовал добавлять и удалять кавычки, но, похоже, не могу набрать правильное сочетание. Любые советы или хитрости, безусловно, приветствуются.
Спасибо,
~ ck в Сан-Диего
Комментарии:
1. вы получаете какие-либо ошибки или это просто сбой без предупреждения? Вы пробовали вводить оператор ELSE, чтобы вывести что-нибудь, сообщающее вам, является ли ваше утверждение «СУЩЕСТВУЕТ», если оно ложно?
Ответ №1:
Динамический SQL так не работает.
Вы по-прежнему не можете передать параметры динамической строке, которая будет использоваться вместо имен объектов.
Вы должны создать строку запроса самостоятельно, вручную заменив @DBName
фактическое значение. Однако вы можете использовать параметр в правой части уравнения без каких-либо кавычек.
Кроме того, при вводе имени объекта в запрос всегда используйте QUOTENAME
функцию. Имя будет корректно экранировано, поэтому не будет sql-инъекции или нежелательного поведения, вызванного определенными символами в имени объекта.
SET @sql = N' IF EXISTS (SELECT NAME FROM master.sys.databases sd where name = @DBName)
BEGIN
ALTER DATABASE ' quotename(@DBName, '[') N' SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE ' quotename(@DBName, '[') N' SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DROP DATABASE ' quotename(@DBName, '[') N'
END';
Комментарии:
1. Да, вы были правы. Ваше первое решение сработало. В итоге я сделал это ОБЪЯВИТЬ @DBName sysname SET @DBName = ‘RepairInformation’ ОБЪЯВИТЬ @sql NVARCHAR(500) УСТАНОВИТЬ @sql = N, если СУЩЕСТВУЕТ (ВЫБЕРИТЕ ИМЯ Из master.sys.databases sd, где name = N «‘ @DBName «‘) НАЧАТЬ ИЗМЕНЯТЬ БАЗУ ДАННЫХ [‘ @DBName ‘] УСТАНОВИТЬ RESTRICTED_USER С НЕМЕДЛЕННЫМ ОТКАТОМ ИЗМЕНИТЬ БАЗУ ДАННЫХ [‘ @DBName ‘] УСТАНОВИТЬ SINGLE_USER С ОТКАТ НЕМЕДЛЕННОГО УДАЛЕНИЯ БАЗЫ ДАННЫХ [‘ @DBName ‘] ЗАВЕРШЕНИЕ’ ВЫПОЛНЕНИЯ sp_executesql @sql
Ответ №2:
Попробуйте это:
USE [master]
GO
DECLARE @sql NVARCHAR(500)
SET @sql = N' IF EXISTS (SELECT NAME FROM master.sys.databases sd where name =@DBName)
BEGIN
ALTER DATABASE [@DBName] SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE [@DBName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DROP DATABASE [@DBName]
END';
EXECUTE sp_executesql @sql, N'@DBName sysname', @DBName = 'ReapirInformation'
GO
Комментарии:
1. нет, это не сработало. Он анализирует нормально, но не удаляет базу данных.
2. @Hcabnettek, вы уверены, что имя базы данных указано правильно. Проверьте ‘ReapirInformation’.
Ответ №3:
- Вы указали @DBName в
if exists
запросе, поэтому он не будет рассматривать его как переменную привязки и, следовательно, не будет заменять переданное имя. Таким образом, поиск по ‘@DBName’ ничего не находит,if exists
имеет значение false, и SQL выполнен. - Как только вы исправите 1, вы заключите в кавычки @DBName в следующих трех строках, поэтому не будете заменять значение, а попытаетесь изменить @DBName, а не значение @DBName, и попытаетесь удалить @DBName, а не значение @DBName.
-
Я не думаю, что вы можете использовать переменные bind для имени базы данных, но я могу ошибаться. Если вы не можете, вам нужно будет создать строку динамически:
set @SQL = N' IF EXISTS (SELECT NAME FROM master.sys.databases sd where name =@DBName) BEGIN ALTER DATABASE ' QUOTENAME('ReapirInformation') N' SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE ALTER DATABASE ' QUOTENAME('ReapirInformation') N' SET SINGLE_USER WITH ROLLBACK IMMEDIATE DROP DATABASE ' QUOTENAME('ReapirInformation') N' END';
[OT: Почему stackoverflow теряет разрывы строк при копировании и вставке?]
Или что-то вроде:
SET @sql = N' IF EXISTS (SELECT NAME FROM master.sys.databases sd where name =@DBName)
BEGIN
ALTER DATABASE ##@DBName## SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE ##@DBName## SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DROP DATABASE ##@DBName##
END';
SET @DBName = N'ReapirInformation';
SET @sql = replace(@sql, N'##@DBNAME##', QUOTENAME(@DBName)
EXECUTE sp_executesql @sql, N'@DBName sysname', @DBName = @DBName
Предупреждение непроверено, нет удобного доступа к SQL Server.