Como usar transações com DDL do SQL Server?

20

Eu tenho uma tabela de logon na qual todas as inserções são feitas por um único procedimento armazenado.

CREATE TABLE dbo.LogTable(
    LogRefnr int IDENTITY(1, 1) NOT NULL,
    LogQuery varchar(255) NOT NULL,
    LogTime datetime NOT NULL,
    logQueryDuration int NULL,
    LogSessionID int NULL,
 CONSTRAINT PK_Log PRIMARY KEY CLUSTERED  (LogRefnr)
)
go


Create procedure DBO.LogInsert ( @Query varchar(255), @time datetime, @duration int, @SessinID int) as
begin
    Insert into LogTable ( LogRefnr, LogQuery, logQueryDuration, LogSessionID)
    Values  (@Query, @time, @duration, @SessinID);
end;
GO

Atualmente, existem cerca de 45500000 linhas nessa tabela e desejo direcionar o log para uma tabela diferente.

Minha ideia é usar o seguinte script

begin Transaction

exec sp_rename LogTable, LogTableOld;

CREATE TABLE dbo.LogTable(
    LogRefnr int IDENTITY(46000000, 1) NOT NULL,            -- greater than select max(LogRefnr) from LogTableOld
    LogQuery varchar(255) NOT NULL,
    LogTime datetime NOT NULL,
    logQueryDuration int NULL,
    LogSessionID int NULL,
 CONSTRAINT PK_Log2 PRIMARY KEY CLUSTERED  (LogRefnr);
)
go

sp_recompile LogTable;
go

Commit;

Isso funciona e tem impacto mínimo em outros procedimentos que chamam LogInsert?

bernd_k
fonte
2
Você não precisa do sp_recompile. O cache do procedimento para qualquer objeto que use o objeto dbo.LogTable expirará automaticamente quando você renomear o objeto.
precisa saber é o seguinte

Respostas:

24

Sim. As transações se aplicam a DDL e abrangem lotes.

Eu faria algo assim. Observe o uso de SERIALIZABLE ISOLATION para garantir o isolamento completo e o XACT_ABORT, que forçará uma reversão a qualquer erro.

SET XACT_ABORT ON
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
begin Transaction
GO
exec sp_rename LogTable, LogTableOld;
GO
CREATE TABLE dbo.LogTable(
    LogRefnr int IDENTITY(46000000, 1) NOT NULL,            -- greater than select max(LogRefnr) from LogTableOld
    LogQuery varchar(255) NOT NULL,
    LogTime datetime NOT NULL,
    logQueryDuration int NULL,
    LogSessionID int NULL,
 CONSTRAINT PK_Log2 PRIMARY KEY CLUSTERED  (LogRefnr);
)
go
EXEC sp_recompile LogTable;
go

Commit;
gbn
fonte
11
Você pode vincular a uma referência que mostre que as transações do SQL Server se aplicam a lotes DDL e de extensão? As páginas BOL óbvias não mencionam isso.
Nick Chammas
2
@ Nick: Eu nunca procurei um. Eu sei que funciona como eu o uso o tempo todo. Depende de você acreditar em mim ou me refutar ou tentar por si mesmo. Obviamente, as transações são por conexão como várias declarações set que eu uso. Uma conexão consiste em vários lotes. O que mais você precisa?
gbn 5/08/11
Acredito em você, mas esperava alguma documentação "oficial" que enumere todas as ações vinculadas a transações explícitas e quais não. Por exemplo, variáveis ​​de tabela não são afetadas por reversões de transação (o que, para mim, viola o Princípio da Menor Surpresa ).
Nick Chammas
2
Quase o mesmo código, mas a transação não funciona: stackoverflow.com/questions/47868213/…
aleyush