Справка по синтаксису Sql Server 2008 sp_executesql — я думаю, что мои цитаты неверны

#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:

  1. Вы указали @DBName в if exists запросе, поэтому он не будет рассматривать его как переменную привязки и, следовательно, не будет заменять переданное имя. Таким образом, поиск по ‘@DBName’ ничего не находит, if exists имеет значение false, и SQL выполнен.
  2. Как только вы исправите 1, вы заключите в кавычки @DBName в следующих трех строках, поэтому не будете заменять значение, а попытаетесь изменить @DBName, а не значение @DBName, и попытаетесь удалить @DBName, а не значение @DBName.
  3. Я не думаю, что вы можете использовать переменные 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.