Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
简单的t-sql而不是触发器_Sql_Sql Server_Tsql - Fatal编程技术网

简单的t-sql而不是触发器

简单的t-sql而不是触发器,sql,sql-server,tsql,Sql,Sql Server,Tsql,有人能帮助解决简单t-sql脚本的触发器问题吗?我使用非常简单的触发器将数据从一个表复制到另一个表(这些表之间没有关系)。当我第一次尝试在触发器创建之后直接插入数据时(从同一个脚本),我得到了期望的结果,但接下来的所有尝试都会失败,并出现下一个提示:“当前事务无法提交,并且无法支持写入日志文件的操作。回滚事务。'我不明白这是什么意思。请看下面的触发器: CREATE TRIGGER AuthorInsert ON Author INSTEAD OF INSERT AS BEGIN -- //-

有人能帮助解决简单t-sql脚本的触发器问题吗?我使用非常简单的触发器将数据从一个表复制到另一个表(这些表之间没有关系)。当我第一次尝试在触发器创建之后直接插入数据时(从同一个脚本),我得到了期望的结果,但接下来的所有尝试都会失败,并出现下一个提示:“
当前事务无法提交,并且无法支持写入日志文件的操作。回滚事务。
'我不明白这是什么意思。请看下面的触发器:

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 -//

没有理由发布表的图表,因为它非常原始(正如我在上面提到的,这些表之间没有直接的关系)。我的脚本出了什么问题?这个奇怪的错误到底意味着什么?

我不确定
开始尝试
块的意义是什么。很明显,您希望确保有一个名为
作者的
角色
——但是您真的需要每次都在触发器中检查这个吗?你不能现在就填充它,再也不用检查了吗

  • 求你了
  • 我在模块主体周围添加了适当的
    BEGIN/END
    包装,并添加了
    SET NOCOUNT ON
  • 我将
    COUNT(*)从inserted
    更改为
    (如果存在)
    。如果你真的不在乎实际计数是1、10还是6000,那么就没有理由费心检索实际计数
  • 我从插入的
    中删除了对值使用变量。正如@marc_指出的,您不能依赖于此,因为触发器是按语句而不是按行触发的。因此,如果您有一个多行插入,您现有的触发器将只处理一个任意行
  • 我删除了
    TRY/CATCH
    块,在触发器中尤其如此,因为它不仅影响触发器代码,还影响外部事务(如您所见)。特别是在您的情况下,可能每次在第一次运行此触发器后都会引发异常
  • 我不得不猜测
    作者
    的列名。除了在那篇文章中陈述的原因外,它还使其他人更容易帮助您重新编写代码

我不确定
begintry
块的意义是什么。很明显,您希望确保有一个名为
作者的
角色
——但是您真的需要每次都在触发器中检查这个吗?你不能现在就填充它,再也不用检查了吗

  • 求你了
  • 我在模块主体周围添加了适当的
    BEGIN/END
    包装,并添加了
    SET NOCOUNT ON
  • 我将
    COUNT(*)从inserted
    更改为
    (如果存在)
    。如果你真的不在乎实际计数是1、10还是6000,那么就没有理由费心检索实际计数
  • 我从插入的
    中删除了对值使用变量。正如@marc_指出的,您不能依赖于此,因为触发器是按语句而不是按行触发的。因此,如果您有一个多行插入,您现有的触发器将只处理一个任意行
  • 我删除了
    TRY/CATCH
    块,在触发器中尤其如此,因为它不仅影响触发器代码,还影响外部事务(如您所见)。特别是在您的情况下,可能每次在第一次运行此触发器后都会引发异常
  • 我不得不猜测
    作者
    的列名。除了在那篇文章中陈述的原因外,它还使其他人更容易帮助您重新编写代码

您的基本缺陷是:您假设插入的
伪表只包含一行-事实并非如此!如果SQL语句影响多行,则将为该语句调用一次触发器,并且插入的
将包含多行数据。当你写你的触发器时,你需要考虑到这一点!
BEGIN TRY/INSERT'Author'
的意义是什么?您为什么认为
@@IDENTITY+1
是安全的?你认为你能准确地预测你将获得下一个身份值,并且永远不会有差距吗?你能解释一下为什么这需要一个代替触发器而不是后触发器吗?在这种情况下使用什么类型的触发器真的很重要吗?除非你通常想要回滚插入,或者需要在插入之前处理其他事情,通常后触发器工作得更好,因为您不必自己制定insert语句。如果你不想(或不知道),你不必回答这个问题,但是如果有理由这必须是一个代替触发器,那么最好知道在我的回答中考虑到这一点。你的基本缺陷是:你假设
插入的
伪表只包含一行-事实并非如此!如果SQL语句影响多行,则将为该语句调用一次触发器,并且插入的
将包含多行数据。当你写你的触发器时,你需要考虑到这一点!
BEGIN TRY/INSERT'Author'
的意义是什么?您为什么认为
@@IDENTITY+1
是安全的?你认为你能准确地预测你将获得下一个身份值,并且永远不会有差距吗?你能解释一下为什么这需要一个代替触发器而不是后触发器吗?在这种情况下使用什么类型的触发器真的很重要吗?除非你通常想要回滚插入,或者需要在插入之前处理其他事情,通常后触发器工作得更好,因为您不必自己制定insert语句。如果你不想(或不知道),你不必回答这个问题,但是如果有理由这必须是一个而不是一个触发器,那么知道在我的回答中考虑到这一点会很好。
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