Sql Server 2008 sp_executesql справка по синтаксису - я думаю, что мои цитаты не верны - PullRequest
2 голосов
/ 09 июня 2011

Использование 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 в Сан-Диего

Ответы [ 3 ]

2 голосов
/ 09 июня 2011

Динамический 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';
0 голосов
/ 09 июня 2011
  1. Вы указали @DBName в запросе if exists, поэтому он не будет обрабатывать ее как переменную связывания и, следовательно, не будет заменять переданное имя. Таким образом, поиск в поиске '@DBName' находит ничего, if exists ложно и SQL выполняется.
  2. Как только вы исправите 1, вы цитируете @DBName в следующих трех строках, поэтому не будете подставлять значение и будут пытаться изменить @DBName, а не значение @DBName, и попытаться удалить @DBName не значение @ DBName.
  3. Я не думаю, что вы можете использовать переменные связывания для имени базы данных, но я могу ошибаться. Если вы не можете, вам нужно построить строку динамически:

    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, удобно.

0 голосов
/ 09 июня 2011

Попробуйте это:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...