AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 342033
Accepted
Vaccano
Vaccano
Asked: 2024-08-30 07:25:26 +0800 CST2024-08-30 07:25:26 +0800 CST 2024-08-30 07:25:26 +0800 CST

Se um gatilho executar uma atualização, ele SEMPRE terá o mesmo registro de data e hora para uma tabela temporal?

  • 772

Fundo

Aqui está um exemplo próximo do que estou trabalhando:

CREATE TABLE sandboxTesting.TemporalTest (    
    GroupNumber VARCHAR(25) NOT NULL,
    StartEffectiveWhen DATE NOT NULL,
    EndEffectiveWhen DATE NULL,
    ModifiedWhen DATETIME NULL,
    IsReady BIT NOT NULL DEFAULT 0,
    RowValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
    RowValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
    PERIOD FOR SYSTEM_TIME (RowValidFrom, RowValidTo),
    CONSTRAINT PK_TemporalTest PRIMARY KEY CLUSTERED  
    (
        GroupNumber, StartEffectiveWhen
    )
) WITH (SYSTEM_VERSIONING=ON (HISTORY_TABLE=sandboxTesting.TemporalTestHistory))
GO 

CREATE TRIGGER sandboxTesting.OnModify ON sandboxTesting.TemporalTest AFTER UPDATE AS
BEGIN
    
    UPDATE  temporalTst
    SET     temporalTst.IsReady = 0,
            temporalTst.ModifiedWhen = GETDATE()
    FROM    sandboxTesting.TemporalTest temporalTst
            JOIN deleted del
                ON del.GroupNumber = temporalTst.GroupNumber
                AND del.StartEffectiveWhen = temporalTst.StartEffectiveWhen
    WHERE   -- All business columns go here with OR statements in between them.
            -- The idea is that if anything changes except the IsReady flag, then we 
            -- set the IsReady back to false.  (IsReady has to be set by itself)
            del.EndEffectiveWhen <> temporalTst.EndEffectiveWhen 
            OR (del.EndEffectiveWhen IS NULL AND temporalTst.EndEffectiveWhen IS NOT NULL)
            OR (del.EndEffectiveWhen IS NOT NULL AND temporalTst.EndEffectiveWhen IS NULL)
END
GO

-- Insert new test
INSERT INTO [sandboxTesting].[TemporalTest] ([GroupNumber], [StartEffectiveWhen], [EndEffectiveWhen],  [ModifiedWhen])
VALUES ('12345', '2024-01-1', NULL, NULL)
GO

-- Set is as ready 
UPDATE  sandboxTesting.TemporalTest
SET     IsReady = 1
WHERE   GroupNumber = '12345' AND StartEffectiveWhen = '2024-01-1'
GO 

-- Change the End date
UPDATE  sandboxTesting.TemporalTest
SET     EndEffectiveWhen = '2024-09-02'
WHERE   GroupNumber = '12345' AND StartEffectiveWhen = '2024-01-1'
        
-- Set the new end date as ready for billing.
UPDATE  sandboxTesting.TemporalTest
SET     IsReady = 1
WHERE   GroupNumber = '12345' AND StartEffectiveWhen = '2024-01-1'
GO 


-- Select the Data
SELECT * FROM sandboxTesting.TemporalTest for SYSTEM_TIME ALL 
ORDER BY GroupNumber, StartEffectiveWhen desc, RowValidFrom DESC, RowValidTo DESC, ModifiedWhen desc

-- Select the Raw Data (for comparison)
SELECT * FROM sandboxTesting.TemporalTest
UNION ALL 
SELECT * FROM sandboxTesting.TemporalTestHistory
ORDER BY GroupNumber, StartEffectiveWhen desc, RowValidFrom DESC, RowValidTo DESC, ModifiedWhen desc

Quando executo isso, este é o primeiro resultado:

Número do grupo InícioEfetivoQuando FimEfetivoQuando ModificadoQuando Está pronto LinhaVálidaDe LinhaVálidaPara
12345 2024-01-01 2024-09-02 2024-08-29 17:15:28.587 1 2024-08-29 23:15:28.5764223 9999-12-31 23:59:59.9999999
12345 2024-01-01 NULO NULO 1 2024-08-29 23:15:28.5295658 2024-08-29 23:15:28.5764223
12345 2024-01-01 NULO NULO 0 2024-08-29 23:15:28.4826980 2024-08-29 23:15:28.5295658

E o segundo conjunto de saída se parece com isto:

Número do grupo InícioEfetivoQuando FimEfetivoQuando ModificadoQuando Está pronto LinhaVálidaDe LinhaVálidaPara
12345 2024-01-01 2024-09-02 2024-08-29 17:15:28.587 1 2024-08-29 23:15:28.5764223 9999-12-31 23:59:59.9999999
12345 2024-01-01 2024-09-02 2024-08-29 17:15:28.587 0 2024-08-29 23:15:28.5764223 2024-08-29 23:15:28.5764223
12345 2024-01-01 2024-09-02 NULO 1 2024-08-29 23:15:28.5764223 2024-08-29 23:15:28.5764223
12345 2024-01-01 NULO NULO 1 2024-08-29 23:15:28.5295658 2024-08-29 23:15:28.5764223
12345 2024-01-01 NULO NULO 0 2024-08-29 23:15:28.4826980 2024-08-29 23:15:28.5295658

Isso é diferente porque o primeiro resultado da consulta usa a for SYSTEM_TIME ALLcláusula, enquanto o segundo apenas consulta os dados brutos.

A diferença é que, no primeiro conjunto de dados, a segunda e a terceira linhas do segundo conjunto de dados foram filtradas. Elas foram removidas porque a segunda e a terceira linhas têm uma data de início e uma data de término que são as mesmas. (Basicamente dizendo que essas linhas nunca estiveram realmente em vigor.)

Pergunta

O que preciso saber é se posso confiar que essa "diferença de tempo zero" sempre estará presente para dados que foram atualizados por meio de um AFTERgatilho? (Preciso escrever algumas consultas que falharão se esse não for o caso.)

O que quero dizer com isso é o seguinte: se meu servidor estivesse sendo bombardeado por milhares de consultas, todas realizando quantidades absurdas de E/S e cálculos, os valores RowValidFrome RowValidTopara a segunda e terceira linhas do segundo conjunto de dados ainda teriam uma diferença de 0?

Em outras palavras, esses valores são os mesmos por causa da lógica da transação? Ou são os mesmos porque meu servidor é rápido e não está realmente sob nenhuma pressão agora?

sql-server
  • 2 2 respostas
  • 229 Views

2 respostas

  • Voted
  1. Rodger Kong
    2024-08-30T11:07:03+08:002024-08-30T11:07:03+08:00

    No cenário que você construiu, NÃO, a 2ª linha não pode ter certeza de que foi atualizada pelo AFTERgatilho. Mas a 3ª linha pode ser tratada como uma ação que dispara o gatilho.

    Executei seu script no meu laptop lento, o resultado é este Meu Resultado . O tempo de¶ da 2ª linha não é o mesmo. Mas a 3ª linha tem o mesmo tempo de¶, isso ocorre porque uma linha TemporalTestfoi modificada várias vezes na mesma transação. No seu exemplo, fase 1: atualização EndEffectiveWhen, isso foi registrado na 3ª linha; fase 2: AFTER TRIGGERfoi disparado para atualização IsReady, isso foi registrado na 2ª linha. A tabela de histórico marca esses registros com o mesmo ValidFrome ValidTotempo para identificar que as atualizações foram realizadas na mesma PK dentro da mesma transação e registra o tempo de término da transação nas últimas linhas do histórico ValidTo. Você pode verificar a descrição no documento .

    • 3
  2. Best Answer
    Paul White
    2024-08-30T20:08:09+08:002024-08-30T20:08:09+08:00

    posso depender dessa "diferença de tempo zero" sempre presente para dados que foram atualizados por meio de um gatilho AFTER

    Não. Linhas com um período de validade zero aparecem sempre que você atualiza a mesma linha várias vezes dentro da mesma transação (mesmo que nenhum valor de coluna seja realmente alterado). Apenas a alteração de linha final (efetiva) dentro de uma transação pode ter um período de validade diferente de zero.

    No seu caso, o gatilho faz a alteração final, então seu período de validade será diferente de zero, em geral. Ele ainda pode ter duração zero se toda a transação e uma alteração subsequente forem concluídas abaixo da resolução do timer em uso.

    Lembre-se de que um gatilho é executado na transação da declaração de gatilho. Mesmo que não haja transação explícita ou implícita, sempre há a transação autocommit iniciada pela atualização de origem.


    Quando executo seu exemplo como um único lote com planos de execução desativados para minimizar atrasos entre instruções, vejo:

    Resultados a toda velocidade

    A ASOFconsulta retorna apenas duas linhas porque as instruções são concluídas tão rapidamente que três das entradas do histórico têm períodos de validade zero.

    Em particular, alterar a data de término, a execução subsequente do gatilho e, finalmente, definir IsReady como 1 parecem ser concluídos instantaneamente. Como resultado, a ASOFvisualização faz parecer que IsReady nunca foi definido como zero.

    Você pode evitar esse tipo de resultado em seus testes introduzindo um pequeno WAITFORatraso no gatilho ou ativando planos de execução reais no SSMS. Em qualquer caso, o atraso extra evitará que operações muito rápidas sejam registradas com períodos de validade zero.

    Com os planos de execução em andamento, vejo:

    Resultados do SSMS com planos de execução em

    Os atrasos significam que a ASOFconsulta agora mostra ambas as transições IsReady de 0 para 1.

    Você também pode executar suas instruções de teste uma de cada vez, em vez de todas de uma vez em um único lote.


    Nada disso alterará o fato de que as alterações feitas por um gatilho ocorrem dentro da transação da instrução de gatilho, serão a alteração final em uma linha específica dentro dessa transação e, portanto, o único evento com um período de validade diferente de zero.

    • 2

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve