Pergunta

Suponha que eu tenha uma tabela de banco de dados que tenha uma coluna timedate da última vez em que foi atualizada ou inserida. O que seria preferível:

  1. Atualize um gatilho no campo.
  2. Peça ao programa que está fazendo o campo de inserção/atualização.

A primeira opção parece ser a mais fácil, já que eu nem preciso recompilar para fazê -lo, mas isso não é realmente um grande negócio. Fora isso, estou tendo problemas para pensar em qualquer motivo para fazer um sobre o outro. Alguma sugestão?

Foi útil?

Solução

A primeira opção pode ser mais robusta porque o banco de dados manterá o campo. Isso vem com a possível sobrecarga do uso de gatilhos.

Se você pudesse ter outros aplicativos escrevendo para esta tabela no futuro, por meio de suas próprias interfaces, eu iria com um gatilho para que você não esteja repetindo essa lógica em nenhum outro lugar.

Se o seu aplicativo for praticamente isso ou qualquer outro aplicativo acessaria o banco de dados através do mesmo datalayer, evitaria esse pesadelo que os gatilhos podem induzir e colocar a lógica diretamente em seu datalayer (SQL, ORM, Stored Procs, etc. ).

É claro que você precisaria garantir que seu tempo de tempo (seu aplicativo, PCs de seus usuários, seu servidor SQL) seja preciso em ambos os casos.


Sobre por que eu não gosto de gatilhos:

Talvez eu tenha sido precipitado chamando -os de pesadelo. Como tudo o mais, eles são apropriados com moderação. Se você os usar para coisas muito simples como essa, eu poderia embarcar.

É quando o código do gatilho fica complexo (e caro) que os gatilhos começam a causar muitos problemas. Eles são um imposto oculto sobre todas as consultas de inserção/atualização/exclusão que você executa (dependendo do tipo de gatilho). Se esse imposto for aceitável, eles podem ser a ferramenta certa para o trabalho.

Outras dicas

Você não mencionou 3. Use um procedimento armazenado para atualizar a tabela. O procedimento pode definir registros de data e hora conforme desejado.

Talvez isso não seja viável para você, mas eu não vi isso mencionado.

Eu diria que o gatilho, caso alguém use algo além do seu aplicativo para atualizar a tabela, você provavelmente também deseja ter um último e usar e usar suser_sname () para isso, assim você pode ver quem fez a atualização

Desde que eu esteja usando um DBMS em cujos gatilhos eu confio, eu sempre iria com a opção de gatilho. Ele permite que os DBMs cuidem do maior número possível de coisas, o que geralmente é uma coisa boa.

Funciona, certifique -se de que, em qualquer circunstância, a coluna Timestamp tenha o valor correto. A sobrecarga seria insignificante.

A única coisa que seria contra os gatilhos é a portabilidade. Se isso não é um problema, acho que não há uma pergunta para qual direção seguir.

Sou um proponente dos procedimentos armazenados para tudo. O seu Proc Atualize pode conter um getDate () para a coluna.

E eu não gosto de gatilhos para esse tipo de atualização. A falta de visibilidade dos gatilhos tende a causar confusão.

Isso parece lógica de negócios para mim ... eu estaria mais disposto a colocar isso no código. Deixe o banco de dados gerenciar o armazenamento de dados ... não mais nem menos.

Os gatilhos são uma bênção e uma maldição.

Bênção: Você pode usá -los para permitir todos os tipos de verificação de restrição personalizada e gerenciamento de dados sem o conhecimento ou as alterações dos sistemas de back -end.

Maldição: Você não sabe o que está acontecendo nas suas costas. Questões de simultaneidade/deadlocks por objetos adicionais trazidos para transações que não eram de origem de origem. Comportamento fantasma, incluindo mudanças no ambiente de sessão, rowcounts não confiáveis. Acionamento excessivo das condições. Penalidades de acesso/desempenho adicionais.

A resposta para esta pergunta (atualiza as datas implicitamente (gatilho) ou explicitamente (código)) pesam muito no contexto. Por exemplo, se você estiver usando a última data de alteração como um campo informativo, poderá alterá -lo apenas quando um 'usuário' realmente faz alterações salientes em uma linha versus um processo automatizado que simplesmente atualiza algum tipo de marcador interno que os usuários não se importam .

Se você estiver usando o gatilho para a sincronização de alterações ou não tiver controle sobre o código que está executando um gatilho faz muito mais sentido.

Meu conselho sobre o gatilho usa -o para ter cuidado. A maioria dos sistemas permite filtrar a execução com base na operação e os campos alterados. O uso adequado de 'antes' vs 'após os gatilhos pode ter um impacto significativo no desempenho.

Finalmente, alguns sistemas são capazes de executar um único gatilho em várias alterações (várias linhas efetuadas em uma transação) seu código deve estar preparado para se aplicar como uma atualização em massa para várias linhas.

Normalmente eu diria que faça o lado do banco de dados, mas depende do seu aplicativo. Se você estiver usando o LINQ-para-SQL, basta definir o campo como registro de data e hora e usar o campo DAL DAL para a concorrência. Ele lida com você automaticamente, portanto, precisar repetir o código é um evento que não seja.

Se você está escrevendo seu dal, porém, seria mais provável que eu lide com isso no lado do banco de dados, pois torna a escrita interfaces de usuário muito mais flexíveis - embora eu provavelmente faria isso em um procedimento armazenado que tenha "público "Acesso e as mesas trancadas - você não quer que nenhum palhaço chegue e ignorando seu procedimento armazenado escrevendo diretamente para as tabelas ... a menos que você planeje fazer do seu DAL um componente independente que qualquer aplicativo futuro deve usar para acessar O banco de dados, nesse caso, você pode codificá -lo diretamente no DAL - é claro, você só deve fazer isso se puder garantir que todos que acessam o banco de dados o estejam fazendo através do seu componente DAL.

Se você vai permitir que o acesso "público" ao banco de dados seja inserido em tabelas, terá que ir com o gatilho, porque, caso contrário, qualquer pessoa pode inserir/atualizar um único campo na tabela e o campo atualizado nunca poderá ser atualizado .

Eu teria a data mantida no banco de dados, ou seja, um gatilho, procedimento armazenado etc. Na maioria dos aplicativos orientados ao banco de dados, o aplicativo do usuário não será o único meio pelo qual os usuários de negócios recebem dados. Existem ferramentas de relatório, extratos, SQL do usuário etc. Também há atualizações e correções feitas pelo DBA para que o aplicativo também não fornecerá a data.

Mas, honestamente, a razão pela qual eu não faria isso no aplicativo é que você não tem controle sobre a data/hora na máquina cliente. Eles podem estar rolando de volta para obter mais dias de uma licença de teste em algo ou podem apenas querer fazer coisas ruins no seu programa.

Você pode fazer isso sem o gatilho se o seu banco de dados suportar valores padrão nos campos. Por exemplo, no SQL Server 2005, tenho uma tabela com um campo criado assim:

create table dbo.Repository
   (
    ...
   last_updated     datetime default getdate(),
    ...
   )

Em seguida, o código de inserção deixa esse campo fora da lista de campos de inserção.

Esqueci que só funcionou para a primeira inserção - também tenho um gatilho de atualização, para atualizar os campos de data e colocar uma cópia do registro atualizado na minha tabela de histórico - que eu postaria ... mas o editor continua errando No meu código ...

Finalmente:

create trigger dbo.Repository_Upd on dbo.Repository instead of update
as
--**************************************************************************
--   Trigger: Repository_Upd
--    Author: Ron Savage
--      Date: 09/28/2008
--
-- Description:
-- This trigger sets the last_updated and updated_by fields before the update
-- and puts a copy of the updated row into the Repository_History table.
--
-- Modification History:
-- Date        Init  Comment
-- 10/22/2008  RS    Blocked .prm files from updating the history as they
--                   get updated every time the cfg file is run.
-- 10/21/2008  RS    Updated the insert into the history table to use the
--                   d.last_updated field from the Repository table rather
--                   than getdate() to avoid micro second differences.
-- 09/28/2008  RS    Created.
--**************************************************************************
begin
   --***********************************************************************
   -- Update the record but fill in the updated_by, updated_system and
   -- last_updated date with current information.
   --***********************************************************************
   update cr set
      cr.filename           = i.filename,
      cr.created_by         = i.created_by,
      cr.created_system     = i.created_system,
      cr.create_date        = i.create_date,
      cr.updated_by         = user,
      cr.updated_system     = host_name(),
      cr.last_updated       = getdate(),
      cr.content            = i.content
   from
      Repository cr

      JOIN Inserted i
         on (i.config_id = cr.config_id);


   --***********************************************************************
   -- Put a copy in the history table
   --***********************************************************************
   declare @extention varchar(3);
   select @extention = lower(right(filename,3)) from Inserted;

   if (@extention <> 'prm')
      begin
      Insert into Repository_History
         select
            i.config_id,
            i.filename,
            i.created_by,
            i.created_system,
            i.create_date,
            user           as updated_by,
            host_name()    as updated_system,
            d.last_updated,
            d.content
         from
            Inserted i

            JOIN Repository d
               on (d.config_id = i.config_id);
      end
end

Ron

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top