Question

Is it possible to create a trigger that will check if a specific field is being set to NULL (from a single-line or multi-line update), and if it is, to revert that field back to its initial value?

I've searched on the site but not found anything that matches my exact requirements.

A bit of background:

We have two applications (a time management web app and microsoft project server) sending updates to each other about the resources in our organisation. When a change is made in either system, it sends that update to the other system. However, there are certain fields that only exist in the time management web app (table name resource), and MSP server is forcing one of these fields (field name GLMaskingValue) to NULL with some of its updates (not all, as far as I can tell).

I have no access to the code, just the web app database, and I don't want to make the whole update statement fail (which I gather I could do using table constraints) - I just want to revert this one field back when and if someone tries to change it to NULL.

I'm going down the route of triggers but there may well be a much better way of doing this - if so please enlighten me!

Was it helpful?

Solution

Something like this:

CREATE TRIGGER trig_test
ON dbo.t
AFTER update
AS
update t
set t.x = d.x
from t as t
join deleted d 
on t.id = d.id -- use the primary key of the table instead of id
where t.x is null

OTHER TIPS

If its only updates that are the problem, yes you can enforce that with an "instead of update" trigger, caveat is that you have to write the update statement to apply the changes:

create table data (id int not null, name varchar(50), postcode varchar(50), sex bit, primary key(id))
go
create trigger tg_data_before on data instead of update as 
begin
  set nocount on
  update data 
    set name = coalesce(c.name, b.name),
      postcode = coalesce(c.postcode, b.postcode),
      sex = coalesce(c.sex, b.sex)
  from data a
  join deleted b on a.id = b.id
  join inserted c on a.id = c.id
end
go

insert data values (1, 'sven', '1234', 0)
insert data values (2, 'lars', '2345', 0)
insert data values (3, 'foo', '3456', 1)

update data set name = null
update data set postcode = null where id = 1
update data set postcode = 'zoink' where id in (2,3)
update data set sex = 1-sex

select * from data

drop table data

But I think it would be better to just use "not null" and fix the client code, which is clearly doing the wrong thing (explictly nulling a field which you don't want to be null, or doing a non-guarded insert/merge):

create table data (id int not null, name varchar(50) not null, postcode varchar(50) not null, sex bit not null, primary key(id))

Sounds like a good plan until the code can be corrected. Here's a multi-row, multi-column trigger. The benefit here is that it will only perform the update if one or both of the two columns have have changed. Also note that it only act on rows/columns where the previous values were not null.

CREATE TRIGGER tr_resource_nullcheck ON resource
FOR UPDATE
AS
SET NOCOUNT ON
IF (UPDATE(GLMaskingValue) OR UPDATE(Column2))
BEGIN
  update r
    set r.GLMaskingValue = isnull(r.GLMaskingValue, d.GLMaskingValue)
        r.column2 = isnull(r.column2, d.column2)

  from resource r
  join deleted d on d.resourceId = r.resourceId
  where (r.GLMaskingValue is null and d.GLMaskingValue is not null) 
  or (r.column2 is null and d.column2 is not null)
END
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top