2016-08-19 3 views
1

Я хотел бы выполнить этот запрос в хранимой процедуре, но я получаю 2 ошибки:SQL Server: инструкция USE в хранимой процедуре

a database of USE instruction not allowed in a procedure, function, or a trigger.

Incorrect syntax near the keyword 'CREATE'. (Microsoft SQL Server, Error: 154).

Мой код:

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[usp_copytable_TEST] 
    @SourceServer nvarchar(255), 
    @SourceDatabase nvarchar(255), 
    @SourceSchema nvarchar(255), 
    @DestinationSchema nvarchar(255) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE 
     @SQL NVARCHAR(MAX), 
     @id uniqueidentifier = NEWID() 

    BEGIN 
     IF NOT EXISTS (SELECT * 
         FROM INFORMATION_SCHEMA.TABLES 
         WHERE TABLE_SCHEMA = 'dbo' 
         AND TABLE_NAME = 'TablesLog_TEST') 
      CREATE TABLE [dbo].[TablesLog_TEST] 
      (
       [id] [uniqueidentifier] NOT NULL, 
       [SourceServer] [nvarchar](255) NULL, 
       [SourceDatabase] [nvarchar](255) NULL, 
       [SourceSchema] [nvarchar](255) NULL, 
       [source] [nvarchar](max) NULL, 
       [destination] [nvarchar](255) NULL, 
       [timestamp] [datetime] NULL, 
       [message] [nvarchar](max) NULL, 
       [type] [smallint] NULL 
      ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

     INSERT INTO dbo.TablesLog_TEST 
      SELECT 
       @id, @SourceServer, @SourceDatabase, @SourceSchema, 
       'GetAllTables', @DestinationSchema, CURRENT_TIMESTAMP, 
       'Start Copy', 1 
     BEGIN TRY 
      INSERT INTO dbo.TablesLog_TEST 
       SELECT 
        @id, @SourceServer, @SourceDatabase, @SourceSchema, 
        'GetAllTables', @DestinationSchema, CURRENT_TIMESTAMP, 
        'try 1', 1 

      -- Create destination schema if it doesn't exist 
      SELECT @SQL = N'IF NOT EXISTS (SELECT * FROM [' + @SourceDatabase + '].SYS.SCHEMAS WHERE NAME = [' + @DestinationSchema + ']) 
      BEGIN 
       SELECT @SQL = N'USE ['+ @SourceDatabase +']; 
           EXEC(''CREATE SCHEMA '+ @DestinationSchema +' '')' 
       EXEC sp_executesql @SQL 
      END' 
     EXEC sp_executesql @SQL   

    END TRY 
    BEGIN CATCH 
     INSERT INTO dbo.TablesLog_TEST 
      SELECT @id, @SourceServer, @SourceDatabase, @SourceSchema, 
      'GetAllTables', @DestinationSchema, CURRENT_TIMESTAMP, 
      'ERROR: ' + ERROR_MESSAGE(), 0 

    END CATCH 

    --Return value: 
    SELECT 1; 
END 

Кто-то может мне помочь пожалуйста?

С наилучшими пожеланиями

Тонкий

ответ

0

Тонкий

Этот код будет работать

SELECT @SQL = N'IF NOT EXISTS (SELECT * FROM [' + @SourceDatabase + '].SYS.SCHEMAS WHERE NAME = ''' + @DestinationSchema + ''') 
     BEGIN 
      DECLARE @SQL NVARCHAR(MAX); 

      SELECT @SQL = N''USE ['+ @SourceDatabase +']; 
          EXEC(''''CREATE SCHEMA '+ @DestinationSchema +' '''')'' 
      EXEC sp_executesql @SQL 
     END' 
    EXEC sp_executesql @SQL   

Как Сандип пятнистый вам нужно объявить переменную @sql в динамическом коде. Когда вы используете sp_executesql для запуска динамического кода, он эффективно работает изолированно от вашего основного хранимого процесса и, таким образом, ничего не знает о каких-либо переменных, объявленных ранее. Вы увидите, что я добавил еще несколько одинарных кавычек, чтобы все работало; также заменил [] в инструкции SELECT, чтобы @DestinationSchema отображался как текст, а не имя столбца.

В стороне, знаете ли вы, как использовать debug tools в SQL Server Management Studio? Введите следующее:

EXEC usp_copytable_TEST 'SourceServer', 'SourceDatabase', 'SourceSchema', 'DestinationSchema' 

самостоятельно в новом окне запроса. Вместо того, чтобы нажимать F5 для выполнения, нажмите ALT + F5, это вызовет сеанс отладки, и теперь вы можете пройти через код по строкам, смотреть переменные и так далее. Вы найдете это очень полезным, так как вы можете увидеть значения ваших динамических строк SQL.

0

Попробуйте:

USE [CORE] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
Create PROCEDURE [dbo].[usp_copytable_TEST] 
    @SourceServer nvarchar(255), 
    @SourceDatabase nvarchar(255), 
    @SourceSchema nvarchar(255), 
    @DestinationSchema nvarchar(255) 
AS 
BEGIN 

    SET NOCOUNT ON; 
    DECLARE 
     @SQL NVARCHAR(MAX), 
     @id uniqueidentifier = NEWID() 

    BEGIN 
     If NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'TablesLog_TEST') 
     CREATE TABLE [dbo].[TablesLog_TEST](
      [id] [uniqueidentifier] NOT NULL, 
      [SourceServer] [nvarchar](255) NULL, 
      [SourceDatabase] [nvarchar](255) NULL, 
      [SourceSchema] [nvarchar](255) NULL, 
      [source] [nvarchar](max) NULL, 
      [destination] [nvarchar](255) NULL, 
      [timestamp] [datetime] NULL, 
      [message] [nvarchar](max) NULL, 
      [type] [smallint] NULL 
     ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

    INSERT INTO dbo.TablesLog_TEST SELECT @id, @SourceServer,@SourceDatabase, @SourceSchema, 'GetAllTables', @DestinationSchema, CURRENT_TIMESTAMP, 'Start Copy', 1 

    BEGIN TRY 
     INSERT INTO dbo.TablesLog_TEST SELECT @id, @SourceServer,@SourceDatabase, @SourceSchema, 'GetAllTables', @DestinationSchema, CURRENT_TIMESTAMP, 'try 1', 1 

     -- Create destination schema if it doesn't exist 
     SELECT @SQL = N'IF NOT EXISTS (SELECT * FROM [' + @SourceDatabase + '].SYS.SCHEMAS WHERE NAME = [' + @DestinationSchema + ']) 
      BEGIN 
       SELECT @SQL = N''USE ['+ @SourceDatabase +']; 
           EXEC(''CREATE SCHEMA '+ @DestinationSchema +' '')'' 
       EXEC sp_executesql @SQL 
      END' 
     EXEC sp_executesql @SQL   

    END TRY 
     BEGIN CATCH 
      INSERT INTO dbo.TablesLog_TEST SELECT @id, @SourceServer,@SourceDatabase, @SourceSchema, 'GetAllTables', @DestinationSchema, CURRENT_TIMESTAMP, 'ERROR: ' + ERROR_MESSAGE(), 0 

     END CATCH 
    --Return value: 
    SELECT 1; 
    END 
END 
+0

Привет Sandip Patel, Привет Пол Bambury, Спасибо за вашу помощь! Я пробовал, но я получил сообщение, в котором сказано, чтобы объявить переменную @SQL. ОШИБКА. Должна быть объявлена ​​скалярная переменная «@SQL». Но это уже объявлено в начале моей программы! я попытался объявить, но это не нравится :( у вас другое решение? – Slim025

+0

Вы должны объявить эту переменную внутри динамического оператора запроса (красный текст блок) –

+0

Спасибо вам @Sandip Патель за помощь Спасибо вам Павла Bambury для вашей помощи Это работает !!! Проблема заключалась в отсутствии кавычек при построении моего динамического SQL. – Slim025

0

Вы, кажется, отсутствуют некоторые кавычки при построении динамического SQL

Попробуйте

SELECT @SQL = N'IF NOT EXISTS (SELECT * FROM [' + @SourceDatabase + '].SYS.SCHEMAS WHERE NAME = [' + @DestinationSchema + ']) 
      BEGIN 
       SELECT @SQL = N''USE ['+ @SourceDatabase +']; 
           EXEC(''CREATE SCHEMA '+ @DestinationSchema +' '')'' 
       EXEC sp_executesql @SQL 
      END' 
+0

Здравствуйте, Пол, , когда я выполняю хранимую процедуру, у меня есть это сообщение об ошибке: Связанный сервер поставщика OLE DB «SQLNCLI11» «MyServerName, 10001» «Отсроченная подготовка не может быть завершена». и в журнале у меня есть: ОШИБКА: Неправильный синтаксис рядом с 'SourceDatabase_NAME'. – Slim025

0

Спасибо @Sandip Patel за вашу помощь, Спасибо Пол Бамбери за вашу помощь Это работает !!! Проблема заключалась в отсутствии кавычек при построении динамического SQL. Как это: --Create Temporary table SELECT @SQL ='SELECT * INTO SANDBOX.dbo.TempTables FROM OPENQUERY(['[email protected]+'], '' SELECT * FROM ICTNONID.information_schema.tables where TABLE_SCHEMA = '''''[email protected]+''''' '') WHERE TABLE_NAME NOT in (SELECT IGNORENAME FROM CORE.dbo.CopyTablesProdIgnore where IGNORETYPE = ''TABLE'' AND schemaname = '''[email protected]+''') ' EXEC sp_executesql @SQL

Смежные вопросы