Sql 调用存储过程时触发器失败
我真的希望有人能帮我 我有一个触发器来处理向表中插入新记录的操作。正如您将在下面看到的,此触发器将一条记录插入到另一个表中,该表依次在该表上执行一个触发器,该触发器调用一个存储过程(我尝试在触发器本身中执行该操作,但失败了,并且很难测试失败的位置,因此我将其移动到自己的小单元中) 在存储过程中,会调用从Active Directory数据库(ADSI)提取信息并更新新插入的记录。但是,这就是触发器调用时失败的地方。当我通过简单地执行它来调用它,并传递要更新的记录时,它工作得非常好。。。谁能给我指出正确的方向吗?请 YYY中的触发器#1 XXX中的触发器#2 存储过程:Sql 调用存储过程时触发器失败,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,我真的希望有人能帮我 我有一个触发器来处理向表中插入新记录的操作。正如您将在下面看到的,此触发器将一条记录插入到另一个表中,该表依次在该表上执行一个触发器,该触发器调用一个存储过程(我尝试在触发器本身中执行该操作,但失败了,并且很难测试失败的位置,因此我将其移动到自己的小单元中) 在存储过程中,会调用从Active Directory数据库(ADSI)提取信息并更新新插入的记录。但是,这就是触发器调用时失败的地方。当我通过简单地执行它来调用它,并传递要更新的记录时,它工作得非常好。。。谁能给我指
USE [XXX]
GO
/****** Object: StoredProcedure [dbo].[UpdateNames] Script Date: 08/04/2014 08:14:52 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:
-- Create date:
-- Description:
-- =============================================
ALTER PROCEDURE [dbo].[UpdateNames]
@NamesID int
AS
BEGIN
SET FMTONLY OFF;
SET NOCOUNT ON;
DECLARE @eID varchar(10);
DECLARE @TAG varchar(10);
DECLARE @SQL nvarchar(555);
DECLARE @DBresults as table (
eID nvarchar(100),
mobile nvarchar(100),
mail nvarchar(100),
phone nvarchar(100),
name nvarchar(50),
legacyExchangeDN nvarchar(100),
Title nvarchar(100),
homeDirectory nvarchar(100));
DECLARE @mobile nvarchar(100)
DECLARE @mail nvarchar(100)
DECLARE @phone nvarchar(100) = 'Error'
DECLARE @name nvarchar(100)
DECLARE @legacyExchangeDN nvarchar(100)
DECLARE @Title nvarchar(100) = 'Error'
DECLARE @homeDirectory nvarchar(100)
SET @eID = (Select eID from [XXX].[dbo].[tblNames] Where NamesID = @NamesID)
SET @SQL = N'SELECT * FROM OpenQuery ( ADSI, ''SELECT homeDirectory,Title,legacyExchangeDN,displayName, telephoneNumber, mail, mobile,samAccountName
FROM ''''LDAP://domain.com''''
WHERE objectClass = ''''User'''' and samAccountName = ''''' + @eID+ ''''''') As tblADSI'
INSERT INTO @DBresults
EXEC sp_executesql @SQL
DECLARE DBcursor CURSOR FOR
SELECT * from @DBresults;
Open DBcursor; FETCH DBCursor into @eID, @mobile, @mail, @phone, @Name, @legacyExchangeDN, @Title, @homeDirectory;
CLOSE DBcursor; DEALLOCATE DBcursor;
UPDATE XXX.dbo.tblNames
SET Job_Title = @Title,
Phone = @Phone
Where NamesID = @NamesID;
END
正如我在评论中所说的——触发器应该非常小、灵活、精简——不要在触发器内部进行任何广泛而耗时的处理,并避免任何可能导致性能瓶颈的事情,尤其是游标 其原因是,每当发生
INSERT
操作时,触发器都会被触发,您无法控制调用它的时间和次数。当触发器工作时,主应用程序将等待并挂起-因此,不要让这太长时间-从触发器快速返回以继续使用主应用程序
我的做法是:
- 创建一个新的单独表,在其中插入一些关键信息,这些信息来自第一个原始触发器
CREATE TABLE NewCustodianInserted ( ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, CaseID VARCHAR(20), Tag VARCHAR(255), Handled BIT DEFAULT (0) );
- 更改
表上的原始触发器,将这些关键信息插入新的“命令”表中:保管人
- 在一个单独的过程中,例如计划每5分钟运行一次的SQL Server代理作业(或对应用程序有意义的任何作业),读取“命令”表,让新的保管人处理,调用该长时间运行的存储过程,从中更新Active Directory。在这里,因为它是从主应用程序异步运行的,所以可以使用游标,因为您希望为新表中的每一行调用存储过程,所以几乎必须使用游标
CREATE PROCEDURE HandleNewCustodians AS BEGIN SET NOCOUNT ON; DECLARE @CaseID VARCHAR(20); DECLARE @Tag VARCHAR(255); DECLARE @NamesID varchar(10); DECLARE CustodianCursor CURSOR FAST_FORWARD FOR SELECT CaseID, Tag FROM dbo.NewCustodianInserted WHERE Handled = 0 OPEN CustodianCursor FETCH NEXT FROM CustodianCursor INTO @CaseID, @Tag; WHILE @@FETCH_STATUS = 0 BEGIN SELECT @NamesID = NameID FROM [XXX].[dbo].[tblNames] WHERE eID = @Tag AND CaseID = @CaseID EXEC dbo.UpdateNames @NamesID; FETCH NEXT FROM CustodianCursor INTO @CaseID, @Tag; END CLOSE CustodianCursor; DEALLOCATE CustodianCursor; END
CREATE TABLE NewCustodianInserted
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
CaseID VARCHAR(20),
Tag VARCHAR(255),
Handled BIT DEFAULT (0)
);
CREATE TRIGGER [dbo].[NewCustodian]
ON [YYY].[dbo].[Custodians]
AFTER INSERT
AS BEGIN
SET NOCOUNT ON;
-- insert key pieces about the new custodian into "command" table
INSERT INTO dbo.NewCustodianInserted (CaseID, Tag)
SELECT i.CaseId, i.Tag
FROM Inserted i
WHERE NOT EXISTS (SELECT * FROM [XXX].[dbo].[tblNames] WHERE eID = i.Tag AND CaseID = i.CaseID)
END
CREATE PROCEDURE HandleNewCustodians
AS
BEGIN
SET NOCOUNT ON;
DECLARE @CaseID VARCHAR(20);
DECLARE @Tag VARCHAR(255);
DECLARE @NamesID varchar(10);
DECLARE CustodianCursor CURSOR FAST_FORWARD
FOR
SELECT CaseID, Tag FROM dbo.NewCustodianInserted WHERE Handled = 0
OPEN CustodianCursor
FETCH NEXT FROM CustodianCursor INTO @CaseID, @Tag;
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @NamesID = NameID
FROM [XXX].[dbo].[tblNames] WHERE eID = @Tag AND CaseID = @CaseID
EXEC dbo.UpdateNames @NamesID;
FETCH NEXT FROM CustodianCursor INTO @CaseID, @Tag;
END
CLOSE CustodianCursor;
DEALLOCATE CustodianCursor;
END