SQL Server 2008插入触发器未触发

时间:2011-04-05 16:54:42

标签: sql-server permissions triggers sql-agent-job

我在一个只执行作业的表上有一个INSERT触发器。

示例:

CREATE TABLE test
(
    RunDate smalldatetime
)

CREATE TRIGGER StartJob ON test 
AFTER INSERT 
AS
    EXEC msdb.dbo.sp_start_job 'TestJob'

当我向此表中插入记录时,会触发该作业而不会出现任何问题。但是,有一些人的权限低于我的权限(仅限数据库上的db_datareader / db_datawriter);他们能够在表格中插入记录,但触发器不会触发。

我是SQL Server新手,我的印象是用户不需要提升权限来触发触发器(我认为这是一个很大的好处!)。这是触发级别或作业级别的权限问题吗?我该怎么做才能解决这个限制?

2 个答案:

答案 0 :(得分:2)

触发器将在调用者的上下文中执行,调用者可能有也可能没有访问msdb的权限。这似乎是你的问题。有几种方法可以使用Execute As扩展这些权限;它们在link

中非常详细

在触发器中使用模拟:

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队列来处理存储过程激活。您的用户上下文将简单地调用Send On队列,而在异步过程中,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;
*/

答案 1 :(得分:1)

这将是工作级别的权限。您可以将这些用户分配给MSDB中的SQLAgentReaderRole,以便能够启动作业,考虑到它们将被添加到拥有该作业的组中。如果他们不属于拥有这份工作的团队,那就更难了。