2011-02-17 4 views
1

특정 단어가있는 새 행을 삽입 할 때 발생하는 데이터베이스 트리거를 만들려고 전자 메일 경고를 보냅니다. 전자 메일 알림은 해당 코드를 실행할 때 작동하며 전자 메일 조각을 제거하고 다른 것으로 바꾸면 트리거가 작동합니다. 여기 트리거 시도 할 때 SQL 트리거가 작동하지 않는다

코드입니다 :

ALTER TRIGGER CheckForDirty 
ON dbo.Messages 
FOR INSERT,UPDATE 
AS 

DECLARE @MESSAGETEXT varchar(max) 
DECLARE @BADWORD1 varchar(50) 

SET @MESSAGETEXT = (SELECT Body FROM inserted) 
SET @BADWORD1 = 'BadWord' 

IF CHARINDEX(@BADWORD1, @MESSAGETEXT) > 0 
BEGIN 

    EXEC msdb.dbo.sp_send_dbmail @recipients='[email protected]', 
    @subject = 'Test e-mail sent from database mail', 
    @body = 'Someone said something dirty' 

END 
GO 
+0

http://stackoverflow.com/questions/3360158/cursor-inside-trigger-not-working의 중복, –

답변

1

트리거에서 전자 메일 송신 코드를 분리하는 것이 좋습니다 - 트리거에서 "보류중인 전자 메일"테이블에 필요한 정보를 입력하십시오. 그런 다음 정기적으로 테이블을 확인하고 전자 메일을 보내는 작업을 만듭니다.

또한 다중 행 삽입 및 업데이트에 대처하기 위해 트리거를 다시 작성해야합니다. inserted은 여러 행을 포함 할 수있는 의사 테이블입니다. 난 당신이 더 많은 정보에 의존 할 수 구성하고있는 메시지의 실제 몸이 연루되는 메시지를 식별하는 데 도움이 있으리라 믿고있어 있지만

CREATE TRIGGER CheckForDirty 
ON dbo.Messages 
FOR INSERT,UPDATE 
AS 

INSERT INTO PendingEmails (Recipients,Subject,Body) 
SELECT '[email protected]','Test e-mail sent from database mail','Someone said something dirty' 
FROM inserted 
WHERE CHARINDEX('BadWord',Body) > 0 

:

그래서 나는이 같은 트리거 뭔가를 써서 .


좋아, 우리는 전체 예제에이를 구축하기 위하여려고하는 경우에, 우리는 PendingEmails 정의해야합니다 :

CREATE TABLE PendingEmails (
    PendingEmailID int IDENTITY(1,1) not null, 
    Recipients varchar(max) not null, 
    Subject nvarchar(255) not null, 
    Body nvarchar(max) not null, 
    constraint PK_PendingEmails PRIMARY KEY (PendingEmailID) 
) 

을 그리고 지금 우리가 처리 할 수있는 저장된 프로 시저를 쓸 것이다 대기중인 이메일 :

CREATE PROCEDURE DispatchPendingEmails 
AS 
    declare @PendingEmailID int 
    declare @Recipients varchar(max) 
    declare @Subject nvarchar(255) 
    declare @Body nvarchar(max) 

    while exists(select * from PendingEmails) 
    begin 
     select top 1 @PendingEmailID = PendingEmailID,@Recipients = Recipients, 
      @Subject = Subject, @Body = Body from PendingEmails 

     exec msdb.dbo.sp_send_dbmail @recipients = @Recipients, @subject = @Subject, @body = @Body 

     delete from PendingEmails where PendingEmailID = @PendingEmailID 
    end 

마지막으로 작업을 만들어야합니다. 나는 일반적으로 SSMS를 통해이 작업을 수행하지만, 스크립트를 원한다면 (sp_add_jobstep 행에서 다른 데이터베이스 이름을 대체해야하며이 작업은 5 분마다 디스패치를 ​​실행하도록 설정되어 있습니다. 저장된 procs는 모두 잘 작동합니다.) MSDN에 설명 : 기본적으로

USE [msdb] 
GO 
DECLARE @jobId BINARY(16) 
EXEC msdb.dbo.sp_add_job @job_name=N'DispatchPendingEmails', 
     @enabled=1, 
     @notify_level_eventlog=0, 
     @notify_level_email=2, 
     @notify_level_netsend=2, 
     @notify_level_page=2, 
     @delete_level=0, 
     @category_name=N'[Uncategorized (Local)]', 
     @owner_login_name=N'sa', @job_id = @jobId OUTPUT 
select @jobId 
GO 
EXEC msdb.dbo.sp_add_jobserver @job_name=N'DispatchPendingEmails', @server_name = N'SYSTEMS86\SQL2K8' 
GO 
USE [msdb] 
GO 
EXEC msdb.dbo.sp_add_jobstep @job_name=N'DispatchPendingEmails', @step_name=N'ExecSP', 
     @step_id=1, 
     @cmdexec_success_code=0, 
     @on_success_action=1, 
     @on_fail_action=2, 
     @retry_attempts=0, 
     @retry_interval=0, 
     @os_run_priority=0, @subsystem=N'TSQL', 
     @command=N'exec DispatchPendingEmails', 
     @database_name=N'Database', --<-- This needs editing 
     @flags=0 
GO 
USE [msdb] 
GO 
EXEC msdb.dbo.sp_update_job @job_name=N'DispatchPendingEmails', 
     @enabled=1, 
     @start_step_id=1, 
     @notify_level_eventlog=0, 
     @notify_level_email=2, 
     @notify_level_netsend=2, 
     @notify_level_page=2, 
     @delete_level=0, 
     @description=N'', 
     @category_name=N'[Uncategorized (Local)]', 
     @owner_login_name=N'sa', 
     @notify_email_operator_name=N'', 
     @notify_netsend_operator_name=N'', 
     @notify_page_operator_name=N'' 
GO 
USE [msdb] 
GO 
DECLARE @schedule_id int 
EXEC msdb.dbo.sp_add_jobschedule @job_name=N'DispatchPendingEmails', @name=N'QuiteOften', 
     @enabled=1, 
     @freq_type=4, 
     @freq_interval=1, 
     @freq_subday_type=4, 
     @freq_subday_interval=5, 
     @freq_relative_interval=0, 
     @freq_recurrence_factor=1, 
     @active_start_date=20110218, 
     @active_end_date=99991231, 
     @active_start_time=0, 
     @active_end_time=235959, @schedule_id = @schedule_id OUTPUT 
select @schedule_id 
GO 
+0

그러면 테이블에서 메시지를 보낼 작업을 어떻게 만들 수 있습니까? – bookbinder

+0

SQL 2008 Express에서이 작업을 수행 할 수 있습니까? 아니면 SQL 2008 표준을 설치해야합니까? – bookbinder

+0

@bookbinder - 작업 그룹 버전이 필요합니다 (최소한). –

1

첫 번째 추측은 권한 것입니다. 이메일을 실행할 때 수동으로 보내려면 트리거를 실행할 때와 다른 계정으로 실행하고 있습니까? 필자는 사용자 계정에서 코드를 테스트 한 다음 사용 권한이 적은 다른 계정으로 응용 프로그램을 실행하기 전에이를 보았습니다. 모든 사용자가 올바른 메일 그룹에 속하는지 확인해야합니다.

+0

내가 운영하는 가까운 투표를 피하기 위해 충분히 틀림없이 단지 다른 있지만, 내 관리자 계정에있는 코드. 실제 상황이 발생하면 기본 SQL 계정으로 실행됩니다. 어떻게 작동하도록 권한을 변경합니까? – bookbinder

관련 문제