如何调试T-SQL触发器?

时间:2014-02-26 06:03:31

标签: sql

我有一个表t,它有一个名为trgInsAfter的“after insert”触发器。究竟我该如何调试呢?我不是这方面的专家,因此所执行的问题和步骤可能看起来很愚蠢。

到目前为止我执行的步骤是:  1.通过server instance(使用Windows管理员帐户)

连接到SSMS
  1. 右键单击SSMS左侧树中的触发节点,然后双击打开它,触发器的代码在新的查询窗口中打开(调用此Window-1),如下所示:blah .... ,

    ALTER TRIGGER trgInsAfter AS .... BEGIN ... END
    
  2. 打开另一个查询窗口(调用此Window-2),输入sql将一行插入表t:

    insert t(c1,c2) values(1,'aaa')
    
  3. 在Window-1中设置断点(在触发器代码中)

  4. 在Window-2(插入SQL代码)

  5. 中设置断点
  6. 单击工具栏上的“调试”按钮,而“窗口2”是当前窗口

    插入SQL代码的断点被命中,但是当我查看Window-1时,触发器代码中的断点有一个工具提示'unable to bind SQL breakpoint, object containing the breakpoint not loaded'

  7. 我可以理解这个问题:SSMS如何知道Window-1中的代码是触发器

    我想调试?我不知道在哪里告诉SSMS'嘿,这个查询编辑器中的代码是表t的inssert触发器的代码'

    有什么建议吗?

    由于

4 个答案:

答案 0 :(得分:32)

你实际上是在考虑这个。

我首先在一个窗口中运行此查询(进行设置):

create table X(ID int not null)
create table Y(ID int not null)
go
create trigger T_X on X
after insert
as
    insert into Y(ID) select inserted.ID
go
然后我可以丢弃那个窗口。我打开一个新的查询窗口,写:

insert into X(ID) values (1),(2)

并在该行设置断点。然后我启动调试器(Debug从菜单或工具栏或Alt-F5)并等待(一段时间,调试器从未太快),以便它命中该断点。然后,在那里,我选择了Step Into(F11)。并且(稍微等待之后)打开一个新窗口,这是我的触发器,调试器停止的下一行代码是触发器中的insert into Y...行。我现在可以在触发器中设置我想要的任何其他断点。

答案 1 :(得分:2)

SSMS中有一个DEBUG菜单,但您可能需要在服务器上才能进行调试,因此如果是远程访问,则无法正确设置它。 该调试选项将允许您执行代码,并以此方式进入触发器并进行调试(因为您调试了大多数其他代码)。

Debug menu

如果无法访问调试菜单/功能,则必须“手动”调试:

首先通过将触发器的输入插入调试表来确保触发器正常运行。然后你可以验证它被正确调用。 然后,您可以使用调试表中的值调试触发器的查询,就像调整任何其他SQL查询一样。

答案 2 :(得分:0)

无论出于何种原因,我都无法获得@ Damien_The_Unbeliever的解决方案。 至少,不是附加到表的触发器。当我执行Step Into时,它每次都执行查询而不会进入触发器。

然后我在该方法的评论中注意到,无论如何你都看不到任何表值。

所以......

我最终创建了一个通用的调试表。

USE [Your_DB]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Debug_Table](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](60) NOT NULL,
    [Value] [sql_variant] NULL,
    [Description] [varchar](max) NULL,
    [Captured] [datetime] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

然后在我的触发器中我做了类似的事......

DECLARE @ItemNum nvarchar(128)
SELECT  @ItemNum = Item_Number FROM inserted

DECLARE @debugOn as bit = 1
-- Debug
    IF @debugOn = 1
    BEGIN
        INSERT INTO Debug_Table (Name, Value, Description, Captured)
        VALUES ( 'Item Number', @ItemNum, 'The item number from the inserted table in tr_VaultItemIterations_ZCode_Monitor.', GETDATE())
    END;
-- End Debug

从表中触发触发器后,我可以查看我插入Debug_Table的任何变量。

完成调试后,您可以通过将@debugOn变量更改为0来轻松关闭调试插入,以防将来需要再次调试;或者只是完全删除调试代码。

答案 3 :(得分:0)

我也无法Step Into,它会直接超过INSTEAD OF INSERT触发器。所以我最终用以下方法替换了触发器:

ALTER TRIGGER [MyView_Instead_Insert] 
   ON  [MyView] 
   INSTEAD OF INSERT
AS 
BEGIN
SET NOCOUNT ON

select * into temp from INSERTED

END

创建了一个名为temp的表,其中包含INSERTED的列名和值的exaclty。