Есть ли способ вернуться к блоку TRY после ошибки? - PullRequest
0 голосов
/ 28 сентября 2011

Я хочу проверить в своей хранимой процедуре, содержит ли таблица определенные столбцы.Я хочу поднять ошибку, если такие столбцы существуют, потому что они не разрешены.Сначала я пришел к следующей идее, которая, очевидно, имеет дефект, который я могу понять.

  BEGIN TRY 

  SET @sql = N'SELECT TOP 0 forbidden_column_name1 INTO #t1 FROM ' + @input_table ;
  EXEC @err = sp_executesql @sql ;
  IF @err = 0  -- i.e. if succeeds
    RAISERROR('Input table cannot contain ''forbidden_column_name1''. This name is reserved!', 16, 99) ;

  SET @sql = N'SELECT TOP 0 forbidden_column_name2 INTO #t1 FROM ' + @input_table ;
  EXEC @err = sp_executesql @sql ;
  IF @err = 0  -- i.e. if succeeds
    RAISERROR('Input table cannot contain ''forbidden_column_name2''. This name is reserved!', 16, 99) ;

  SET @sql = N'SELECT TOP 0 forbidden_column_name3 INTO #t1 FROM ' + @input_table ;
  EXEC @err = sp_executesql @sql ;
  IF @err = 0  -- i.e. if succeeds
    RAISERROR('Input table cannot contain ''forbidden_column_name3''. This name is reserved!', 16, 99) ;

  END TRY
  BEGIN CATCH
    IF ERROR_STATE() = 99
    BEGIN
      DECLARE @ErrorMessage NVARCHAR(4000);
      DECLARE @ErrorSeverity INT;
      DECLARE @ErrorState INT;

      SELECT 
          @ErrorMessage = ERROR_MESSAGE(),
          @ErrorSeverity = ERROR_SEVERITY(),
          @ErrorState = ERROR_STATE();

      RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
      RETURN ;
    END
    -- Do nothing and continue execution, if column doesn't exist
  END CATCH

Этот код будет проверять только существование forbidden_column_name1.Другие не проверяются, потому что исключение должно быть вызвано во время проверки forbidden_column_name1: либо из sp_executesql, если столбец не существует, либо из RAISERROR, если столбец делает существует.В любом случае, выполнение переходит к блоку catch и никогда не возвращается.

Мой вопрос заключается в том, есть ли способ заставить выполнение вернуться к блоку TRY, если ошибка на самом деле не является ошибкой , а фактически является чем-то желаемым.В противном случае я должен поместить все проверки в отдельные блоки TRY / CATCH, что делает код немного избыточным.

Ответы [ 3 ]

2 голосов
/ 28 сентября 2011

Почему бы не запросить sys.columns, чтобы определить наличие или отсутствие этих столбцов, вместо того, чтобы пытаться вывести их существование путем запроса таблицы?


, например

IF EXISTS(select * from sys.columns where object_id = OBJECT_ID(@table_name) and name in (
    'forbidden_column1','forbidden_column2','forbidden_column3'))
BEGIN
    RAISERROR('One or more forbidden columns detected. Review the documentation',16,99)
    RETURN
END

--Proceed, knowing that the table doesn't contain the forbidden columns
1 голос
/ 28 сентября 2011

Вы должны будете обернуть каждый отдельный оператор select в блок try / catch.

BEGIN TRY 

    SET @sql = N'SELECT TOP 0 forbidden_column_name1 INTO #t1 FROM ' + @input_table ;
    EXEC @err = sp_executesql @sql ;
    IF @err = 0  -- i.e. if succeeds
        RAISERROR('Input table cannot contain ''forbidden_column_name1''. This name is reserved!', 16, 99) ;
END TRY
BEGIN CATCH
    IF ERROR_STATE() = 99
        EXEC usp_RethrowError
END CATCH

Чтобы не повторяться, вы можете создать для этого процедуру, в которой есть параметры как для имени таблицыи имя столбца.

Определение usp_RethrowError

0 голосов
/ 28 сентября 2011

Не прямой ответ на ваш вопрос, но вам лучше использовать INFORMATION_SCHEMA, чтобы определить, существуют ли столбцы.

Что-то вроде:

IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE 
    TABLE_NAME = @input_table AND COLUMN_NAME IN ('forbidden_column_name1', 'forbidden_column_name2', 'etc'))
BEGIN
    RAISERROR('idiot', 16, 99)
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...