1

是否可以创建一个触发器来检查特定字段是否设置为 NULL(从单行或多行更新),如果是,则将该字段恢复为其初始值?

我在网站上搜索过,但没有找到符合我确切要求的任何内容。

一点背景:

我们有两个应用程序(一个时间管理 Web 应用程序和 microsoft 项目服务器)相互发送有关我们组织中资源的更新。当任一系统发生更改时,它会将更新发送到另一个系统。但是,某些字段仅存在于时间管理 Web 应用程序(表名resource)中,并且 MSP 服务器强制这些字段之一(字段名GLMaskingValue)进行NULL一些更新(据我所知,并非全部) .

我无法访问代码,只能访问 Web 应用程序数据库,而且我不想让整个更新语句失败(我认为我可以使用表约束来做到这一点) - 我只想在何时和如果有人试图将其更改为NULL.

我正在沿着触发器的路线前进,但可能有更好的方法来做到这一点 - 如果是这样,请赐教!

4

3 回答 3

4

像这样的东西:

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
于 2012-09-17T11:40:03.317 回答
3

如果只有更新是问题,是的,您可以使用“而不是更新”触发器强制执行此操作,需要注意的是您必须编写更新语句来应用更改:

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

但我认为最好只使用“not null”并修复客户端代码,这显然是在做错事(明确地将一个你不想为空的字段清空,或者做一个无保护的插入/合并):

create table data (id int not null, name varchar(50) not null, postcode varchar(50) not null, sex bit not null, primary key(id))
于 2012-09-17T12:04:21.537 回答
0

在可以更正代码之前,这听起来是个不错的计划。这是一个多行多列触发器。这样做的好处是它只会在两列中的一列或两列发生更改时才执行更新。另请注意,它仅作用于先前值不为空的行/列。

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
于 2012-09-17T12:05:03.150 回答