SQL Server 2008 триггер вставки не срабатывает - PullRequest
1 голос
/ 05 апреля 2011

У меня есть триггер 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 ]

2 голосов
/ 05 апреля 2011

Триггер будет выполняться в контексте вызывающей стороны, которая может иметь или не иметь разрешения на доступ к msdb. Кажется, это твоя проблема. Есть несколько способов расширить эти разрешения с помощью «Выполнить как»; они очень подробно описаны в этой ссылке

Использовать олицетворение в триггере:

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 голос
/ 05 апреля 2011

Это были бы разрешения на уровне работы. Вы можете назначить этим пользователям SQLAgentReaderRole в MSDB, чтобы они могли запускать задание, учитывая, что они будут добавлены в группу, которой принадлежит задание. Если они не в группе, которая владеет работой, это становится сложнее.

...