Вопрос

Предположим, у меня есть таблица базы данных, в которой есть столбец даты и времени последнего обновления или вставки.Что будет предпочтительнее:

  1. Попросите триггер обновить поле.
  2. Попросите программу, выполняющую вставку/обновление, установить это поле.

Первый вариант кажется самым простым, поскольку для этого мне даже не нужно перекомпилировать, но на самом деле это не так уж и важно.Кроме этого, мне трудно придумать какие-либо причины, чтобы сделать одно лучше другого.Какие-либо предложения?

Это было полезно?

Решение

Первый вариант может быть более надежным, поскольку база данных будет поддерживать поле. Это связано с возможными издержками использования триггеров.

Если бы в будущем вы могли записывать в эту таблицу другие приложения через свои собственные интерфейсы, я бы использовал триггер, чтобы вы не повторяли эту логику где-либо еще.

Если ваше приложение в значительной степени оно или другие приложения будут получать доступ к базе данных через один и тот же слой данных, то я бы избежал того кошмара, который триггеры могут вызвать и поместить логику прямо в ваш слой данных (SQL, ORM, хранимые процессы , так далее.).

Конечно, вам нужно убедиться, что ваш источник времени (ваше приложение, компьютеры ваших пользователей, ваш SQL-сервер) точен в любом случае.

<Ч>

Относительно того, почему я не люблю триггеры:

Возможно, я был опрометчив, называя их кошмаром. Как и все остальное, они уместны в меру. Если вы используете их для очень простых вещей, как это, я мог бы попасть на борт.

Именно когда код триггера становится сложным (и дорогим), триггеры начинают вызывать множество проблем. Они являются скрытым налогом на каждый выполняемый вами запрос вставки / обновления / удаления (в зависимости от типа триггера). Если этот налог приемлем, то они могут быть подходящим инструментом для работы.

Другие советы

Вы не упомянули 3. Используйте хранимую процедуру для обновления таблицы. Процедура может устанавливать временные метки по желанию.

Возможно, это неосуществимо для вас, но я не видел, чтобы это упоминалось.

Я бы сказал, триггер на тот случай, если кто-то использует что-то помимо вашего приложения для обновления таблицы, вы, вероятно, также захотите иметь LastUpdatedBy и использовать для этого SUSER_SNAME (), чтобы вы могли видеть, кто сделал обновление

Пока я использую СУБД, триггерам которой я доверяю, я всегда буду использовать опцию триггера. Это позволяет СУБД позаботиться о как можно большем количестве вещей, что, как правило, хорошо.

При любых обстоятельствах убедитесь, что столбец метки времени имеет правильное значение. Накладные расходы были бы незначительными.

Единственное, что было бы против триггеров, это мобильность. Если это не проблема, я не думаю, что есть вопрос, в каком направлении идти.

Я сторонник хранимых процедур для всего. Ваш процесс обновления может содержать GETDATE () для столбца.

И мне не нравятся триггеры для такого рода обновлений. Отсутствие видимости триггеров приводит к путанице.

Для меня это звучит как бизнес-логика ... Я был бы более склонен поместить это в код. Позвольте базе данных управлять хранением данных ... Не больше и не меньше.

Триггеры - это благословение и проклятие.

Благословение: вы можете использовать их для включения всех видов пользовательской проверки ограничений и управления данными без знания или изменений в бэкэнд-системах.

Проклятие: ты не знаешь, что происходит за твоей спиной. Проблемы / взаимные блокировки параллелизма дополнительными объектами, введенными в транзакции, которые изначально не ожидались. Фантомное поведение, включая изменения среды сеанса, ненадежные счета строк. Чрезмерное срабатывание условий .. дополнительные штрафы за горячую точку / производительность.

Ответ на этот вопрос (Обновление дат неявно (триггер) или явно (код)) обычно имеет большой вес в контексте. Например, если вы используете дату последнего изменения в качестве информационного поля, вы можете изменить ее только в том случае, если «пользователь» действительно вносит существенные изменения в строку по сравнению с автоматизированным процессом, который просто обновляет какой-то внутренний маркер, который не интересует пользователей. .

Если вы используете триггер для синхронизации изменений или у вас нет контроля над кодом, который выполняет триггер, это имеет гораздо больше смысла.

Мой совет по триггеру, используйте его, чтобы быть осторожным. Большинство систем позволяют фильтровать выполнение на основе операции и измененных полей. Правильное использование триггеров «до» и «после» может оказать существенное влияние на производительность.

Наконец, несколько систем способны выполнить один триггер для нескольких изменений (несколько строк, выполненных в транзакции), ваш код должен быть готов к тому, чтобы применить себя как массовое обновление для нескольких строк.

Обычно я бы сказал, делать это на стороне базы данных, но это зависит от вашего приложения. Если вы используете LINQ-to-SQL, вы можете просто установить поле как Timestamp, и ваш DAL будет использовать поле Timestamp для параллелизма. Он обрабатывает это для вас автоматически, поэтому повторение кода не является событием.

Если вы пишете свой DAL самостоятельно, то я бы с большей вероятностью справился с этим на стороне базы данных, поскольку это делает написание пользовательских интерфейсов гораздо более гибким - хотя, я бы, вероятно, сделал это в хранимой процедуре, которая имеет " общедоступный " доступ и таблицы заблокированы - вам не нужно, чтобы какой-либо клоун приходил и обходил вашу хранимую процедуру, записывая непосредственно в таблицы ... если вы не планируете сделать свой DAL автономным компонентом, который любое будущее приложение должно использовать для доступа к базы данных, в этом случае вы можете закодировать ее непосредственно в DAL - конечно, вы должны делать это только в том случае, если вы можете гарантировать, что все, кто обращается к базе данных, делают это через ваш компонент DAL.

Если вы хотите разрешить " общедоступные " доступ к базе данных для вставки в таблицы, тогда вам придется использовать триггер, потому что в противном случае любой может вставить / обновить одно поле в таблице, а обновленное поле никогда не будет обновлено.

Я хотел бы сохранить дату в базе данных, т. е. триггер, хранимую процедуру и т. д. В большинстве ваших приложений, управляемых базой данных, пользовательское приложение не будет единственным средством, с помощью которого бизнес-пользователи получают данные , Есть инструменты отчетности, выдержки, пользовательский SQL и т. Д. Кроме того, администратор базы данных вносит обновления и исправления, для которых приложение также не будет указывать дату.

Но, честно говоря, причина № 1, по которой я бы не делал этого из приложения, заключается в том, что вы не можете контролировать дату / время на клиентском компьютере. Они могут откатить его назад, чтобы получить больше дней на пробную лицензию, или просто захотеть сделать что-то плохое для вашей программы.

Вы можете сделать это без триггера, если ваша база данных поддерживает значения по умолчанию для полей.Например, в SQL Server 2005 у меня есть таблица с полем, созданным следующим образом:

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

тогда код вставки просто исключает это поле из списка полей вставки.

Я забыл, что это сработало только для первой вставки - у меня также есть триггер обновления, чтобы обновить поля даты и поместить копию обновленной записи в мою таблицу истории - которую я бы опубликовал...но редактор продолжает выдавать ошибки в моем коде...

Окончательно:

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

Рон

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top