Почему SQL-сервер продолжает выполняться после raiserror, когда xact_abort идет?

Я думаю, что это лучше всего объяснить следующим рисунком:

enter image description here [/g1]

Чтобы инициализировать вышеизложенное, наберите:

import matplotlib.pyplot as plt
fig = plt.figure()
fig.add_subplot(221)   #top left
fig.add_subplot(222)   #top right
fig.add_subplot(223)   #bottom left
fig.add_subplot(224)   #bottom right 
plt.show()

EDIT: Некоторая дополнительная информация

Следующие комбинации создают асимметричные расположения подзаголовков.

subplot(2,2,[1 3])
subplot(2,2,2)
subplot(2,2,4)

Example 2 [/g2]

Вы также можете использовать оператор двоеточия для указания нескольких местоположений, если они находятся в последовательности.

subplot(2,2,1:2)
subplot(2,2,3)
subplot(2,2,4)

enter image description here [/g3]

Ссылка здесь

85
задан ConcernedOfTunbridgeWells 8 October 2008 в 22:00
поделиться

2 ответа

При использовании блока попытки/выгоды, raiserror код ошибки с серьезностью 11-19 заставит выполнение переходить к блоку выгоды.

Любая серьезность выше 16 является системной ошибкой. Для демонстрации следующих кодовых наборов, блок попытки/выгоды и выполняет хранимую процедуру, которую мы принимаем, перестанет работать:

предполагают, что у нас есть таблица [dbo]. [Ошибки] содержать ошибки предполагают, что у нас есть хранимая процедура [dbo]. [AssumeThisFails], который перестанет работать, когда мы выполним его

-- first lets build a temporary table to hold errors
if (object_id('tempdb..#RAISERRORS') is null)
 create table #RAISERRORS (ErrorNumber int, ErrorMessage varchar(400), ErrorSeverity int, ErrorState int, ErrorLine int, ErrorProcedure varchar(128));

-- this will determine if the transaction level of the query to programatically determine if we need to begin a new transaction or create a save point to rollback to
declare @tc as int;
set @tc = @@trancount;
if (@tc = 0)
 begin transaction;
else
 save transaction myTransaction;

-- the code in the try block will be executed
begin try
 declare @return_value = '0';
 set @return_value = '0';
 declare
  @ErrorNumber as int,
  @ErrorMessage as varchar(400),
  @ErrorSeverity as int,
  @ErrorState as int,
  @ErrorLine as int,
  @ErrorProcedure as varchar(128);


 -- assume that this procedure fails...
 exec @return_value = [dbo].[AssumeThisFails]
 if (@return_value <> 0)
  raiserror('This is my error message', 17, 1);

 -- the error severity of 17 will be considered a system error execution of this query will skip the following statements and resume at the begin catch block
 if (@tc = 0)
  commit transaction;
 return(0);
end try


-- the code in the catch block will be executed on raiserror("message", 17, 1)
begin catch
  select
   @ErrorNumber = ERROR_NUMBER(),
   @ErrorMessage = ERROR_MESSAGE(),
   @ErrorSeverity = ERROR_SEVERITY(),
   @ErrorState = ERROR_STATE(),
   @ErrorLine = ERROR_LINE(),
   @ErrorProcedure = ERROR_PROCEDURE();

  insert #RAISERRORS (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
   values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure);

  -- if i started the transaction
  if (@tc = 0)
  begin
   if (XACT_STATE() <> 0)
   begin
     select * from #RAISERRORS;
    rollback transaction;
    insert into [dbo].[Errors] (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
     select * from #RAISERRORS;
    insert [dbo].[Errors] (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
     values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure);
    return(1);
   end
  end
  -- if i didn't start the transaction
  if (XACT_STATE() = 1)
  begin
   rollback transaction myTransaction;
   if (object_id('tempdb..#RAISERRORS') is not null)
    insert #RAISERRORS (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
     values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure);
   else
    raiserror(@ErrorMessage, @ErrorSeverity, @ErrorState);
   return(2); 
  end
  else if (XACT_STATE() = -1)
  begin
   rollback transaction;
   if (object_id('tempdb..#RAISERRORS') is not null)
    insert #RAISERRORS (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
     values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure);
   else
    raiserror(@ErrorMessage, @ErrorSeverity, @ErrorState);
   return(3);
  end
 end catch
end
23
ответ дан Tom H 5 November 2019 в 16:06
поделиться

Это - Дизайном <глоток> ТМ , как Вы видите на Подключение ответом команды SQL Server на подобный вопрос:

Спасибо за Вашу обратную связь. Дизайном опция набора XACT_ABORT не влияет на поведение оператора RAISERROR. Мы будем полагать, что Ваша обратная связь изменяет это поведение для будущего выпуска SQL Server.

Да, это - что-то вроде проблемы для некоторых, кто надеялся RAISERROR с высокой серьезностью (как 16), совпадет с ошибкой выполнения SQL - это не.

Ваше обходное решение примерно, что необходимо сделать, и использование явной транзакции не имеет никакого эффекта на поведение, которое Вы хотите изменить.

46
ответ дан Ian Boyd 5 November 2019 в 16:06
поделиться