implicit_transactions и exists()

invm
Дата: 14.02.2013 14:18:55
if @@trancount > 0
 rollback;
 
set implicit_transactions on;

if exists(select * from sys.objects)
 print 1;
select 'exists', @@trancount;

select 1;
select 'select', @@trancount;

select 1 where exists(select * from sys.objects);
select 'select + exists', @@trancount;

if @@trancount > 0
 rollback;

set implicit_transactions off;

Есть ли объективные причины такого поведения?
Crimean
Дата: 14.02.2013 14:44:38
похоже, важен "факт аутпута" селекта. ну или намерение вычитки (в смысле "наружу") данных. меняем

select 1

на, скажем

select 1 from sys.objects where 0=1;

и получаем уже открытую транзакцию после этого оператора
DmitryZ78
Дата: 14.02.2013 14:48:51
invm,

совсем не обязательно exists

set implicit_transactions on;
select top 1 * from sys.objects;
select  @@trancount;
DmitryZ78
Дата: 14.02.2013 14:52:02
invm,

совсем не обязательно exists

set implicit_transactions on;
select top 1 * from sys.objects;
select  @@trancount;
invm
Дата: 14.02.2013 15:07:54
Crimean
похоже, важен "факт аутпута" селекта. ну или намерение вычитки (в смысле "наружу") данных
Возможно.
В моем понимании, if exists(...), если там есть обращение или намерение обращения к данным, также должен стартовать транзакцию. Иначе, в режиме неявных транзакций, мы имеем вероятность различных результатов выполнения одного и того же кода, в зависимости от места его вызова. На что и нарвался в одном приложении.
Crimean
Дата: 14.02.2013 15:18:27
invm,

формально, "if exists" отсутствует в перечне операторов, которые стартуют транзакцию :)
invm
Дата: 14.02.2013 15:26:35
Crimean
invm,

формально, "if exists" отсутствует в перечне операторов, которые стартуют транзакцию :)
Ну, формально, merge там тоже отсутствует :) И, опять же формально, выполнение select 1 должно стартовать транзакцию. Ну и, согласно BOL, exists содержит инструкцию select, так что снова формально транзакция должна стартовать :)
invm
Дата: 14.02.2013 17:16:36
Еще один артефакт режима неявных транзакций, который для использующих подобный шаблон хранимок, может стать сюрпризом:
use tempdb;
go

create procedure dbo.spTest
as
begin
 declare @tc int = @@trancount;
 
 if @tc = 0
  begin tran;
 
 begin try
  select 'inner', @@trancount;

  if @tc = 0 and @@trancount > 0
   commit;
 end try
 begin catch
  if @tc = 0 and @@trancount > 0
   rollback;
 end catch;
end;
go

if @@trancount > 0
 rollback;

set implicit_transactions on;

select 'outer', @@trancount;
exec dbo.spTest;
select 'outer', @@trancount;

if @@trancount > 0
 rollback;

set implicit_transactions off;
go
 
drop procedure dbo.spTest;
Наличие открытой транзакции после вызова процедуры в принципе объяснимо. Но где тогда ошибка 266?