简单的T-SQL的INSTEAD OF触发器(Simple t-sql instead of tri

2019-07-21 11:26发布

任何人可以帮助解决简单的T-SQL脚本的问题与触发器板载? 我用很简单的触发将数据从一个表复制到另一个(还有那些表之间没有关系)。 当我尝试后直接触发创建(来自同一个脚本),我得到想要的结果插入在第一次数据,但所有未来的尝试得到了失败,下一个提示:” The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction. The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction. “我很困惑是什么意思。 请看下面的触发:

CREATE TRIGGER AuthorInsert ON Author
INSTEAD OF INSERT
AS
BEGIN -- //- 1 -//
--***************** if insert was correct ********************
    IF (SELECT COUNT(*) FROM INSERTED) > 0
    BEGIN --//- 2 -//
        DECLARE @id int, @roleId int;
        DECLARE @nameId int, @reestrCodeId int, @passportDataId int, @addressId int, @phoneId int;
        SET @nameId = (SELECT INSERTED.NameID FROM INSERTED);
        SET @reestrCodeId = (SELECT INSERTED.ReestrCodeID FROM INSERTED);
        SET @passportDataId = (SELECT INSERTED.PassportDataID FROM INSERTED);
        SET @addressId = (SELECT INSERTED.AddressID FROM INSERTED);
        SET @phoneId = (SELECT INSERTED.PhoneID FROM INSERTED);
        BEGIN TRY
            INSERT INTO Role(RoleName) VALUES('Author');
        END TRY
        BEGIN CATCH
        END CATCH
        SET @roleId = (SELECT Role.RoleID FROM Role WHERE Role.RoleName = 'Author');
        INSERT INTO Employee(NameID, ReestrCodeID, RoleID, PassportDataID, AddressID, PhoneID)VALUES
                            (@nameId, @reestrCodeId, @roleId, @passportDataId, @addressId, @phoneId);
        SET @id = (SELECT Employee.EmployeID FROM Employee WHERE Employee.EmployeID = @@IDENTITY) + 1;
        INSERT INTO Author VALUES(@id, @nameId, @reestrCodeId, @passportDataId, @addressId, @phoneId);
    END -- //- 2 -//
END -- //- 1 -//

没有理由张贴表图,因为它是非常原始的(因为我提出上面有没有直接的表之间的关系)明显。 什么错在我的剧本又是什么actyally那奇怪的错误是什么意思?

Answer 1:

我不知道该点什么BEGIN TRY块。 很显然,要确保有一个Role命名的Author -但你真的需要每次检查这在触发? 你不能现在填充它,从来没有再次检查?

  • 请创建/变更/参照对象时总是使用模式前缀 。
  • 我添加适当BEGIN/END围绕模块主体包装,并增加了SET NOCOUNT ON;
  • 我改变COUNT(*) from insertedIF EXISTS 。 我们没有理由打扰检索,当你真的不在乎,如果是1或10或6000的实际数量。
  • 我删除了值使用变量来自inserted 。 作为@marc_s指出,由于触发器每说法解雇,而不是每你不能靠这个。 所以,如果你有一个多行插入,您现有的触发器将有永远只能处理一个任意行。
  • 我除去TRY/CATCH块。 在大多数情况下,它是更有效的检查侵犯自己,而不是具有SQL Server为你做 ,并在触发尤其如此,因为它不仅对触发器代码也是外部事务的效果(如你所看到的) 。 尤其是在你的情况,其中一个例外是大概每到这个触发器运行后的第一次提出。
  • 我在为列名猜Author 。 请始终在您的列列表SELECTINSERT语句 。 除了在该职位所陈述的理由,这也使得它更容易让别人帮你重新编写代码。
CREATE TRIGGER dbo.AuthorInsert ON dbo.Author INSTEAD OF INSERT
AS
BEGIN
  SET NOCOUNT ON;
  IF EXISTS (SELECT 1 FROM inserted)
  BEGIN
    DECLARE @emps TABLE(id INT, NameID INT);
    DECLARE @RoleID INT;    
    SELECT @RoleID = RoleID FROM dbo.Roles WHERE RoleName = 'Author';

    IF @RoleID IS NULL
    BEGIN
      -- probably not necessary to do this over and over again
      -- unless someone is sabotaging your Roles table.
      INSERT dbo.Roles(RoleName) SELECT 'Author';
      SELECT @RoleID = SCOPE_IDENTITY();
    END

    INSERT dbo.Employee(NameID, ReestrCodeID, RoleID, PassportDataID, 
      AddressID, PhoneID) OUTPUT inserted.EmployeeID, inserted.NameID 
      INTO @emps SELECT NameID, ReestrCodeID, @RoleID, PassportDataID, 
       AddressID, PhoneID FROM inserted;

    -- this seems redundant. If an author is linked to an employee, 
    -- why do we need to store all of this information again?
    INSERT dbo.Author(EmployeeID, NameID, ReestrCodeID, RoleID, 
      PassportDataID, AddressID, PhoneID)
      SELECT e.id, i.NameID, i.ReestrCodeID, @RoleID, 
        i.PassportDataID, i.AddressID, i.PhoneID FROM @emps AS e
        INNER JOIN inserted AS i ON e.NameID = i.NameID;
  END
END
GO


文章来源: Simple t-sql instead of trigger