【问题标题】:Trigger that updates a column on the row where I clicked update触发更新我单击更新的行上的列
【发布时间】:2019-12-10 23:50:03
【问题描述】:

所以我有这张桌子:

ID Name IsDeleted
1  test True
2  test2 False

我目前有以下触发器:

CREATE TRIGGER [dbo].[Trigger_test_IsDeleted]
ON [dbo].[test]
INSTEAD OF DELETE
AS
BEGIN
    SET NOCOUNT ON;
    UPDATE dbo.test
    SET IsDeleted = 1
    WHERE ID = 1;
END

当我单击索引视图中某行上的删除按钮时,我需要启动此触发器并将该行上的 IsDeleted 设置为 1(或 True)。但是,使用上述触发器执行此操作显然只会删除 ID = 1 的行源。如果我省略 WHERE 语句,它会将所有行的 IsDeleted 设置为 true。

我需要我的触发器来动态确定“删除”被按下的位置,并且只删除该行。

我知道在 MySQL 中,您可以通过在删除触发器中使用以下内容来完成此操作:

SET new.IsDeleted = 1

有没有办法获得与“新”相同的效果。在 SQL Server 触发器中?

既然我们在讨论这个话题,我想实现同样的目标,但要更改控制器中的当前代码。这是它现在的样子:

//POST - Delete
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Delete(int? id)
    {
        var test = await _db.Test.FindAsync(id);

        if (test== null)
        {
            return View();
        }
        _db.Test.Remove(test);
        await _db.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

这段代码将实现对数据库的普通删除操作。我想将其更改为将“IsDeleted”设置为 1 而不是删除记录。

【问题讨论】:

  • 为什么不直接从您的代码中执行UPDATE 命令而不是发出DELETE 并假设触发器将始终启用?这是一个危险的假设,因为触发器通常在维护操作期间被禁用,如果有人忘记重新启用触发器,您会很高兴恢复数据。
  • 如果需要使用触发器,请查看inserted and deleted 伪表上的文档。
  • @Dai,我认为即使有人从应用程序外部删除该行,他们也想标记已删除的记录而不是实际删除。但是你的观点也是有效的。
  • @Dai 是的,自从发布问题以来我一直在考虑这个问题,我认为(从调试的角度来看)在我的代码中更改控制器上的删除方法会更好。只是我目前更习惯触发,所以我的问题是基于我的舒适区。此外,我想在我的数据库中强制执行我的业务逻辑以保护它,以防在其上构建新的前端。如果可以的话,我可能会在触发器和控制器上强制执行它,但这可能会导致冲突。

标签: sql-server asp.net-mvc model-view-controller database-trigger


【解决方案1】:

如果你想更新一个标志而不是删除(有些人称之为SOFT DELETE),你应该像这样更新你的触发器:

CREATE TRIGGER [dbo].[Trigger_test_IsDeleted]
ON [dbo].[test]
INSTEAD OF DELETE
AS
BEGIN
    SET NOCOUNT ON;
    UPDATE dbo.test
    SET deleted.IsDeleted = 1
    WHERE ID = deleted.ID; --<-- This is the key point
END

【讨论】:

  • 在没有明确加入 deleted 的情况下是否有效?
  • 是的。当您拥有已删除的 ID 时,您无需加入。请注意,这仅适用于您的情况的单个删除。如果您想支持批量删除 ypu 需要查看更改。
【解决方案2】:

您需要检查“已删除”的虚拟表,并相应地执行更新。例如:

create table test(id int primary key, IsDeleted bit default 0)
go
CREATE OR ALTER TRIGGER [dbo].[Trigger_test_IsDeleted]
ON [dbo].[test]
INSTEAD OF DELETE
AS
BEGIN
    SET NOCOUNT ON;
    UPDATE dbo.test
    SET IsDeleted = 1
    WHERE ID in (select id from deleted); 
END
go 

insert into test(id, IsDeleted) values (1,0),(2,0),(3,0)

delete from test where id = 2

select * from test

输出

id          IsDeleted
----------- ---------
1           0
2           1
3           0

(3 rows affected)

【讨论】:

  • 像魅力一样工作。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-16
相关资源
最近更新 更多