触发器将在调用者的上下文中执行,调用者可能有也可能没有访问 msdb 的权限。这似乎是你的问题。有几种方法可以使用 Execute As 来扩展这些权限;它们在此链接中非常详细
在触发器中使用模拟:
CREATE TRIGGER StartJob ON test
with execute as owner
AFTER INSERT
AS
EXEC msdb.dbo.sp_start_job 'TestJob'
并将数据库设置为可信赖(或阅读以上链接的登录信息):
alter database TestDB set trustworthy on
另一种方法(取决于代理作业执行的操作)是利用 Service Broker 队列来处理存储过程激活。您的用户的上下文将简单地调用队列上的发送,而在异步进程中,SvcBroker 将激活在更高级别用户的上下文中执行的存储过程。我会选择这个解决方案,而不是依赖调用代理作业的触发器。
我想测试对 Service Broker 的调用,所以我编写了这个简单的测试示例。我没有调用 SSIS 包,而是简单地发送一封电子邮件,但这与您的情况非常相似。请注意,我在脚本顶部使用了 SET TRUSTWORTHY ON。请阅读此设置的含义。
要运行此示例,您需要在下面替换您的电子邮件配置文件信息<your_email_address_here>
,等等。
use Master;
go
if exists(select * from sys.databases where name = 'TestDB')
drop database TestDB;
create database TestDB;
go
alter database TestDB set ENABLE_BROKER;
go
alter database TestDB set TRUSTWORTHY ON;
use TestDB;
go
------------------------------------------------------------------------------------
-- create procedure that will be called by svc broker
------------------------------------------------------------------------------------
create procedure dbo.usp_SSISCaller
as
set nocount on;
declare @dlgid uniqueidentifier;
begin try
-- * figure out how to start SSIS package from here
-- for now, just send an email to illustrate the async callback
;receive top(1)
@dlgid = conversation_handle
from SSISCallerQueue;
if @@rowcount = 0
begin
return;
end
end conversation @dlgid;
exec msdb.dbo.sp_send_dbmail
@profile_name = '<your_profile_here>',
@importance = 'NORMAL',
@sensitivity = 'NORMAL',
@recipients = '<your_email_address_here>',
@copy_recipients = '',
@blind_copy_recipients = '',
@subject = 'test from ssis caller',
@body = 'testing',
@body_format = 'TEXT';
return 0;
end try
begin catch
declare @msg varchar(max);
select @msg = error_message();
raiserror(@msg, 16, 1);
return -1;
end catch;
go
------------------------------------------------------------------------------------
-- setup svcbroker objects
------------------------------------------------------------------------------------
create contract [//SSISCallerContract]
([http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer] sent by initiator)
create queue SSISCallerQueue
with status = on,
activation (
procedure_name = usp_SSISCaller,
max_queue_readers = 1,
execute as 'dbo' );
create service [//SSISCallerService]
authorization dbo
on queue SSISCallerQueue ([//SSISCallerContract]);
go
return;
-- usage
/*
-- put a row into the queue to trigger the call to usp_SSISCaller
begin transaction;
declare @dlgId uniqueidentifier;
begin dialog conversation @dlgId
from service [//SSISCallerService]
to service '//SSISCallerService',
'CURRENT DATABASE'
on contract [//SSISCallerContract]
with encryption = off;
begin conversation timer (@dlgId)
TIMEOUT = 5; -- seconds
commit transaction;
*/