Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 как правильно юзать транзакции  [new]
Тэй
Member

Откуда:
Сообщений: 79
есть у меня одна процедура, удаляющая заказ. внутри нее постоянно вылетает ошибка

Текст ошибки
Невозможно выполнить откат pr_Orders_Delete. Не обнаружено транзакции или точки сохранения с этим именем.
Счетчик транзакций после выполнения EXECUTE показывает несовпадение числа инструкций BEGIN и COMMIT. Предыдущее число = 1, текущее число = 2.

а вот сама процедура
ALTER PROCEDURE [dbo].[pr_Orders_Delete] 
	@OrderId bigint,			
	@UserName varchar(256)	
AS
BEGIN
	SET NOCOUNT ON;
	
	DECLARE @ErrorMessage NVARCHAR(4000), @ErrorSeverity INT, @ErrorState INT,
			@NewStatusId smallint = 7	
									    
	BEGIN TRY
		BEGIN TRAN	 pr_Orders_Delete

		EXEC pr_Orders_Move
			@OrderId = @OrderId,	
			@UserName  = @UserName,	
			@NewStatusId = @NewStatusId 	
				
		COMMIT TRAN pr_Orders_Delete
	END TRY
	BEGIN CATCH
		ROLLBACK TRAN pr_Orders_Delete

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

		RAISERROR (@ErrorMessage, -- Message text.
				   @ErrorSeverity, -- Severity.
				   @ErrorState -- State.
				   );
	END CATCH
END


внутри процедуры pr_Orders_Move никаких других действий с транзакциями нет. Поясните пожалуйста, что я делаю не так?
30 янв 14, 21:39    [15497243]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
Тэй,

автор
а вот сама процедура


А где код, который приводит к ошибке?

Зачем Вам именованные транзакции?

автор
никаких других действий с транзакциями нет


Мы Вам верим, безусловно...
30 янв 14, 21:46    [15497258]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
Тэй
Member

Откуда:
Сообщений: 79
pkarklin, пожалела вас, решила, что соль вся в неправильном исп-и транзакций в процедуре верхнего уровня и не стала все полотно постить

ALTER PROCEDURE [dbo].[pr_Orders_Move] 
	@OrderId bigint,			
	@UserName varchar(256),		
	@NewStatusId smallint = NULL,	
	@NewStatusCode varchar(25) = NULL,
    @Quant [int] = NULL,               
	@QuantOrdered [int] = NULL,      
	@DateOrdered [datetime] = NULL,
	@QuantReserved [int] = NULL,     
	@DateReserved [datetime]  = NULL, 
	@QuantArrivedMsk [int] = NULL,      
	@DateArrivedMsk [datetime] = NULL,
	@QuantInTransit [int] = NULL,     
	@DateInTransit [datetime] = NULL,
	@QuantShipped [int] = NULL,        
	@DateShipped [datetime] = NULL,  
	@QuantArrived [int] = NULL,        
	@DateArrived [datetime] = NULL,
	@QuantSold [int] = NULL,          
	@DateSold [datetime] = NULL, 
	@QuantDenied int = NULL,       
	@QuantDefect int = NULL,         
	@Price [decimal](15, 2) = NULL,    
	@SupplierPrice [decimal](15, 2) = NULL 
AS
BEGIN
	SET NOCOUNT ON;

	--найдем пользователя, создавшего движение
	DECLARE @UserId  uniqueidentifier
	
	EXECUTE [logistics].[dbo].[pr_Users_GetIdByName] 
		   @UserName = @UserName
		  ,@ErrorIfNotFound = 1
		  ,@UserId = @UserId OUTPUT
		
	-- Если идентификатор статуса пустой тогда ищем его по коду статуса
	IF (@NewStatusId is NULL)
		SELECT @NewStatusId = O.Id FROM OrdersStatus O WHERE O.Code = @NewStatusCode
	
	IF (@NewStatusId is NULL) 		
		SELECT @NewStatusId =  m.StatusId
		FROM OrderMovings m
		WHERE m.Id = (SELECT MAX(Id)
	  				  FROM OrderMovings
	  				  WHERE OrderId = @OrderId)
	  				  
	-- находим цену  в заказе, чтоб оповестить пользователя 
	-- в том случае, если они изменились	
	DECLARE	@OQuant int = null,@OPrice decimal(15,3) = null, @OSupplierPrice decimal(15,3) = NULL
	
	SELECT @OPrice = Price, 
			@OSupplierPrice = SupplierPrice,
			@OQuant = Quant
	FROM Orders
	WHERE Id = @OrderId	
	
	IF(@Quant IS NULL)
		SELECT @Quant = @OQuant
			
	DECLARE @ret_code int;	
		
 	IF(@SupplierPrice IS NOT NULL AND @SupplierPrice<>@OSupplierPrice)
 		BEGIN	
 			SET @ret_code = 1; 
 			
			UPDATE Orders
			SET PrevPrice = @OPrice,
				Price = @Price,
				SupplierPrice = @SupplierPrice
			WHERE Id = @OrderId
 		END
 	ELSE		
		BEGIN
			UPDATE Orders
			SET PrevPrice = NULL
			WHERE Id = @OrderId
			  				  			
			[color=red]EXEC @ret_code = pr_OrdersStatuses_AllowChange
								@OrderId,
								@NewStatusId[/color]
		END
	
	IF(@Price IS NULL)
		SELECT @Price = @OPrice
		
	IF(@SupplierPrice IS NULL)
		SELECT @SupplierPrice = @OSupplierPrice

			
	IF(@ret_code>=0)
		EXEC [dbo].[pr_OrderMovings_BaseInsert] 
				@OrderId = @OrderId,  
				@StatusId = @NewStatusId,
				@UserId = @UserId,     
				@Quant = @Quant,     
				@QuantOrdered  = @QuantOrdered,
				@DateOrdered  = @DateOrdered,
				@DateReserved  = @DateReserved,
				@QuantReserved = @QuantReserved,
				@DateArrivedMsk = @DateArrivedMsk,
				@QuantArrivedMsk = @QuantArrivedMsk,
				@DateInTransit = @DateInTransit,
				@QuantInTransit = @QuantInTransit,
				@QuantShipped = @QuantShipped,
				@DateShipped = @DateShipped,
				@DateArrived = @DateArrived,
				@QuantArrived = @QuantArrived,
				@DateSold = @DateSold,
				@QuantSold = @QuantSold,
				@QuantDenied = @QuantDenied,
				@QuantDefect = @QuantDefect,
				@Price = @Price,
				@SupplierPrice = @SupplierPrice 
END


а уже в pr_OrdersStatuses_AllowChange
есть проверка
-- Переводить в статус "удалено" можно только из статуса /*InBasket*/
	IF @NewStatusId = 7  /*Delete*/ AND  @OldStatusGroup <> 'InBasket' 
	 BEGIN
		RAISERROR(N'Не удалось удалить заказ №%I64d. Удалять можно только заказы из корзины!',16,1,@OrderId)
		RETURN -1
	END
30 янв 14, 21:55    [15497284]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
Тэй,

В приведенном коде много вызовов ХП. Откуда уверенность, что в них нет инструкций управления транзакциями?!

ЗЫ. Куча кода в хп без транзакций - это за гранью добра и зла.
30 янв 14, 22:50    [15497453]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
Тэй,

Да, забыл ответить на сабжевый вопрос:

SET XACT_ABORT ON

BEGIN TRAN

...

COMMIT
30 янв 14, 22:53    [15497462]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
Тэй
Member

Откуда:
Сообщений: 79
pkarklin,

я конечно могу вам запостить их все, но уж поверьте на слово, что там их нет, открыла и проверила каждую)

а почему такая настороженность к именованным транзакциям? я хочу точно быть уверенной в том, что я откатываю, если в будущем захочу использовать эту процедуру в другой процедуре. возможно, получатся вложенные транзакции.
30 янв 14, 23:41    [15497599]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
Glory
Member

Откуда:
Сообщений: 104751
Тэй
конечно могу вам запостить их все, но уж поверьте на слово, что там их нет, открыла и проверила каждую)

серверу тоже незачем врать про число транзакций
Это легко проверить через переменную @@TRANCOUNT

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

нет в mssql возможности отмены вложенных транзакций. поэтому и непонятно ваше намерение использовать именованные транзакции, если отменить можно только до самой верхней транзакции или до точки сохранения
30 янв 14, 23:46    [15497613]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
Тэй
возможно, получатся вложенные транзакции.


Вложенные транзакции в MS SQL - это миф. Точнее - синтаксический сахар. Скелет решения я Вам уже привел.
30 янв 14, 23:51    [15497630]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
Тэй
Member

Откуда:
Сообщений: 79
спасибо за разъяснения. читая доки как раз вот другое мнение сложилось,

что вроде если я сделаю
BEGIN TRAN a
BEGIN TRAN b

ROLLBACK TRAN b

я откачусь только до b
31 янв 14, 00:11    [15497680]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
Тэй
читая доки...


В доках написано про сэйвпоинты, которых у Вас нет.
31 янв 14, 00:28    [15497734]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
Тэй
Member

Откуда:
Сообщений: 79
pkarklin,

я про них читала, но объясните мне, зачем их в данном случае использовать? мне либо нужно выполнить процедуру от и до: удалить заказ, попутно обновляя некоторые данные, либо не удалять, и тогда уж не обновлять ничего.
31 янв 14, 00:31    [15497741]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
Тэй
зачем их в данном случае использовать?


Абсолютно незачем!

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


Это и называется бизнес-транзакцией.
31 янв 14, 00:36    [15497748]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
Тэй
Member

Откуда:
Сообщений: 79
pkarklin, ну ясно, проводка, как сказали б 1Совцы. спасибо за разъяснения, прям большущее!
31 янв 14, 00:40    [15497754]     Ответить | Цитировать Сообщить модератору
 Re: как правильно юзать транзакции  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
Тэй
ну ясно, проводка, как сказали б ...


О проводках говорят бухгалтеры. И, бизнес-транзакция, это гораздо больше, чем двойная запись.
31 янв 14, 00:47    [15497780]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить