Eu estava brincando com SET IMPLICIT_TRANSACTIONS ON
. Encontrei uma situação em que estou convencido de que o banco de dados está criando e confirmando automaticamente uma transação sem deixá-la aberta. Se eu fizer isso IF EXISTS (SELECT * FROM dbo.t1)
ou qualquer variação, tenho certeza de que uma transação está acontecendo em segundo plano e espero que permaneça aberta se estiver usando transações implícitas.
No entanto, depois de ler os documentos , ele diz algo como:
Isso significa que, se
@@TRANCOUNT = 0
, qualquer uma das instruções Transact-SQL a seguir iniciará uma nova transação.
e a lista que mostra não inclui IF
. No entanto, espero que todas as instruções não encontradas na lista da documentação não saiam @@TRANCOUNT
incrementadas. Então, procurei outra declaração não incluída nessa lista. eu encontrei DECLARE
. No entanto, descobri que, se eu executar uma subconsulta com DECLARE
, obterei o comportamento que esperaria de SET IMPLICIT_TRANSATIONS ON
. Ou seja, se my DECLARE
tiver uma subconsulta, ela será incrementada @@TRANCOUNT
se for zero. Portanto, parece que a documentação é inconsistente consigo mesma
SET IMPLICIT_TRANSACTIONS ON
GO
IF OBJECT_ID('dbo.t1') IS NOT NULL
BEGIN
DROP TABLE dbo.t1
COMMIT
END
GO
CREATE TABLE dbo.t1 (x INT);
COMMIT;
GO
IF CASE WHEN EXISTS (SELECT * FROM dbo.t1) THEN 1 ELSE 0 END = 1 PRINT 'unreachable';
PRINT 'after1 ' + CAST(@@TRANCOUNT AS VARCHAR(MAX)); -- after1 0
DECLARE @x INT = 2;
PRINT 'after2 ' + CAST(@@TRANCOUNT AS VARCHAR(MAX)); -- after2 0
DECLARE @y INT = CASE WHEN EXISTS (SELECT * FROM dbo.t1) THEN 1 ELSE 0 END;
PRINT 'after3 ' + CAST(@@TRANCOUNT AS VARCHAR(MAX)); -- after3 1
GO
WHILE @@TRANCOUNT > 0 ROLLBACK
GO
Por que o DECLARE
incremento @@TRANCOUNT
para um incorporado SELECT
, mas não IF
? O SELECT
incorporado no de IF
alguma forma não está realmente usando uma transação?
Estou usando o SQL Server 13.0.4411.
Eu suspeito que o que você está vendo é porque algumas declarações são transformadas em
SELECT
declarações nos bastidores e outras não. Considere suaDECLARE
declaração final:Isso é apenas uma abreviação para isso:
Que também pode ser escrito assim:
Nesse caso, você esperaria ver
@@TRANCOUNT
incrementado. No entanto, você pode fazer a mesma declaração sobre aIF
declaração? Se eu executar seu código original com planos de execução reais ativados, vejo o seguinte:Não vejo um
SELECT
no plano para a primeira consulta. Eu só vejoCOND WITH QUERY
. Portanto, parece consistente com a documentação.