【问题标题】:Update record using instead of trigger in sql server在sql server中使用而不是触发器更新记录
【发布时间】:2013-04-25 08:08:49
【问题描述】:

我在 sql server 2005 中有触发器 它检查重复记录,然后更新记录。

USE [CheckeCon]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tgUserRoleExistForUpdate] ON [dbo].[Sec_UserRoles]
INSTEAD OF Update
AS
declare @UserRoleId int, @UserId int,@RoleId int, @FromDate datetime,@ToDate datetime,@CntlCreatedBy nvarchar,@CntlModifiedAt nvarchar,@CntlCurLockNo smallint;
select @UserRoleId=i.UserRoleId from inserted i;
select @UserId=i.UserId from inserted i;
select @RoleId=i.RoleId from inserted i;
select @FromDate=i.FromDate from inserted i;
select @ToDate=i.ToDate from inserted i;
select @CntlCreatedBy=i.CntlCreatedBy from inserted i;
select @CntlModifiedAt=i.CntlModifiedAt from inserted i;
select @CntlCurLockNo=i.CntlCurLockNo from inserted i;
BEGIN
-- BEGIN TRAN
IF NOT EXISTS
(
    SELECT  *
    FROM    Sec_UserRoles SEUR
    JOIN    inserted i ON  
            SEUR.RoleId =  i.RoleId
    AND     SEUR.UserId = i.UserId
    Where i.FromDate BETWEEN SEUR.FromDate AND SEUR.ToDate
)
Update Sec_UserRoles Set UserId = @UserId,RoleId = @RoleId,FromDate = @FromDate,ToDate = @ToDate,
        CntlCreatedBy = @CntlCreatedBy,CntlModifiedAt = @CntlModifiedAt,CntlCurLockNo = @CntlCurLockNo Where  UserRoleId = @UserRoleId 
--Commit;
Else
    RAISERROR('User Role Association Already Present',15,1);
   --ROLLBACK; 
End

但问题是它不能更新记录,只引发了我在触发器中给出的错误。 如何使用触发器更新记录?

【问题讨论】:

  • 您的代码只是假设每行都会调用一次触发器。这在 SQL Server 中不是。如果您的 UPDATE 语句影响多行,则触发器将被调用 为该语句一次,并且您的 Inserted 伪表将包含 多行 - 所以您在此处的分配 @ 987654324@ 只会从Inserted 表中分配一个任意值,并忽略Inserted 中的所有其他行 ....
  • 不,不,不,不,不,不,不。 inserted 可以包含 0、1 或多行。所有这些select @scalarvariable=... 语句都可能从不同的 行中选择值。对于您的 IF EXISTS 测试,可能有 some 行的存在测试返回 true,而 some 行返回 false。

标签: sql-server sql-server-2005 triggers


【解决方案1】:

这可能对你有帮助 -

ALTER TRIGGER [dbo].[tgUserRoleExistForUpdate] 

    ON [dbo].[Sec_UserRoles]
    INSTEAD OF UPDATE

AS BEGIN

    IF NOT EXISTS(
        SELECT 1
        FROM INSERTED
    ) RAISERROR('NO ROW IN INSERTED', 16, 1)

    SET NOCOUNT ON;
    SET XACT_ABORT ON;

    DECLARE 
          @UserRoleId INT
        , @UserId INT
        , @RoleId INT
        , @FromDate DATETIME
        , @ToDate DATETIME
        , @CntlCreatedBy NVARCHAR(MAX)
        , @CntlModifiedAt NVARCHAR(MAX)
        , @CntlCurLockNo SMALLINT

    DECLARE cur CURSOR LOCAL READ_ONLY FAST_FORWARD FOR
        SELECT 
              i.UserRoleId
            , i.UserId
            , i.RoleId
            , i.FromDate
            , i.ToDate
            , i.CntlCreatedBy
            , i.CntlModifiedAt
            , i.CntlCurLockNo 
        FROM INSERTED i

    OPEN cur

    FETCH NEXT FROM cur INTO
          @UserRoleId
        , @UserId
        , @RoleId
        , @FromDate
        , @ToDate
        , @CntlCreatedBy
        , @CntlModifiedAt
        , @CntlCurLockNo

    WHILE @@FETCH_STATUS = 0
    BEGIN

        IF NOT EXISTS(
            SELECT 1
            FROM dbo.Sec_UserRoles s
            WHERE @FromDate BETWEEN s.FromDate AND s.ToDate
                AND s.RoleId = @RoleId
                AND s.UserId = @UserId
                --AND s.UserRoleId = @UserRoleId 
        )
        BEGIN

            UPDATE dbo.Sec_UserRoles 
            SET 
                  UserId = @UserId
                , RoleId = @RoleId
                , FromDate = @FromDate
                , ToDate = @ToDate
                , CntlCreatedBy = @CntlCreatedBy
                , CntlModifiedAt = @CntlModifiedAt
                , CntlCurLockNo = @CntlCurLockNo 
            WHERE UserRoleId = @UserRoleId 

        END
        ELSE BEGIN

             RAISERROR('User Role Association Already Present', 0, 1) -- 15      

        END

        FETCH NEXT FROM cur INTO
              @UserRoleId
            , @UserId
            , @RoleId
            , @FromDate
            , @ToDate
            , @CntlCreatedBy
            , @CntlModifiedAt
            , @CntlCurLockNo

    END

    CLOSE cur
    DEALLOCATE cur

END

【讨论】:

  • 正如我在评论中指出的那样,inserted 中可能有 一些EXISTS() 为真,而 other inserted 中为假的行。它应该在UPDATE 上变成某种WHERE 子句条件。
  • 不客气@MonaliJ。如果此解决方案完全适合您,如果您能确认,我将很高兴。
  • 我试过这个解决方案,但它仍然没有更新记录,仍然引发异常......
  • 请尝试更新查询。可能这会删除您的异常。
猜你喜欢
  • 2017-07-22
  • 2021-10-16
  • 2021-07-31
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 2016-11-03
  • 1970-01-01
  • 2011-06-03
相关资源
最近更新 更多