2011-09-20 2 views
0

글쎄, 난 멈출 때마다 전자 메일을 전송하고 백업 루틴을 확인하고 작업을 만드는거야하위 쿼리는 SQL Server의 1 개 이상의 값을 반환 2,005 트리거 [2]

(I가 유용하게 희망 다른 사람에게).

select name as "Nome da Base" , 'L' as Tipo from sys.sysdatabases a 
where name not in ('master','tempdb','model')) 
except 
(select b.database_name, b.type from msdb..backupset b 
where b.backup_start_date >= DATEADD (hour,-2, GETDATE()) 
and type='L') 
union all 
(select name as "Nome da Base", 'D' as Tipo from sys.sysdatabases a 
where name not in ('tempdb','model')) 
except 
(select b.database_name, b.type from msdb..backupset b 
where b.backup_start_date >= DATEADD (day,-1, GETDATE()) 
and type='D' 

2) 작성 :

1) 나는 DB_NAME 및 일정 기간 내에 백업되지었던 backup_type을 반환하는 쿼리를 생성 : 내가 뭘하는 방식이기

CREATE TABLE [dbo].[Alerta_Log_Bkp](
    [Nome da Base] [nvarchar](50) NULL, 
    [Tipo] [nvarchar](8) NULL, 
    [Servidor] [nvarchar](10) NULL, 
    [Hora Verificação] [datetime] NULL 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[Alerta_Log_Bkp] ADD CONSTRAINT [DF_Alerta_Log_Bkp_Servidor] 
    DEFAULT (N'Server_NAME') FOR [Servidor] 
GO 

ALTER TABLE [dbo].[Alerta_Log_Bkp] ADD CONSTRAINT [DF_Alerta_Log_Bkp_Último Backup] 
    DEFAULT (getdate()) FOR [Hora Verificação] 
GO 

3) 삽입을 선택하여 작업을 만든 :

테이블 위의 쿼리의 반환 행을 기록하는
INSERT INTO [dbo].[Alerta_Log_Bkp] 
      ([Nome da Base],[Tipo]) 
(select name as "Nome da Base" , 'L' as Tipo from sys.sysdatabases a 
where name not in ('master','tempdb','model','BA_CMA_OM')) 
except 
(select b.database_name, b.type from msdb..backupset b 
where b.backup_start_date >= DATEADD (hour,-2, GETDATE()) 
and type='L') 
union all 
(select name as "Nome da Base", 'D' as Tipo from sys.sysdatabases a 
where name not in ('tempdb','model')) 
except 
(select b.database_name, b.type from msdb..backupset b 
where b.backup_start_date >= DATEADD (day,-1, GETDATE()) 
and type='D') 
GO 

->이 시점까지는 괜찮습니다.

내 문제는 "Alerta_Log_Bkp"테이블에 라인이 삽입 될 때 전자 메일을 트리거하는 트리거를 만드는 데 있습니다. 삽입물을 1 행만 테스트하면 모든 것이 잘 동작합니다. 그러나 삽입에 두 개 이상의 행이 있으면 다음과 같은 오류 메시지가 나타납니다. "하위 쿼리가 두 개 이상의 값을 반환했습니다. 하위 쿼리가 허용되지 않습니다."

변수를 다음과 같이 설정했기 때문에 발생합니다. 선택 항목이 삽입되었습니다. 그러나 나는 다른 방법을 생각할 수 없다. 여기

트리거입니다 :

Create TRIGGER [dbo].[TR_Alert_mail_BKP] ON [dbo].[Alerta_Log_Bkp] AFTER INSERT AS 

DECLARE @base varchar(50) 
DECLARE @tipo varchar(50) 
DECLARE @servidor varchar(50) 
DECLARE @last_bkp DATETIME 


SET @base = (SELECT "Nome da Base" FROM inserted) 
SET @tipo = (SELECT tipo FROM inserted) 
SET @servidor = (SELECT Servidor FROM inserted) 

create table #temp (base varchar(50), 
        tipo varchar(50), 
        servidor varchar(50)) 
insert into #temp values (@base,@tipo,@servidor) 

SET @last_bkp = (Select MAX(backup_start_date) from msdb..backupset 
       Where database_name = (select base from #temp) 
          and type = (select tipo from #temp)) 

--SET @last_bkp = (Select MAX(backup_start_date) from msdb..backupset 
--    Where database_name = @base and type = @tipo) 

IF @tipo in ('D','L') 
BEGIN 
DECLARE @msg varchar(8000) 
SET @msg = 'The "' [email protected] + '" from database "' + @base + '", of the server "' 
    + @servidor + '", stoped at ' + CAST(@last_bkp as varchar(50)) +'' 
EXEC msdb.dbo.sp_send_dbmail 
    @recipients=N'[email protected]', 
    @body= @msg, 
    @subject = 'Problemas no Backup' , 
    @profile_name = 'PROFILE' 
END 

사람이 방아쇠를 작성하는 또 다른 방법의 실마리가 있는가, 그래서 하위 쿼리 오류가 발생하지 않습니다?

덕분에, 파브

+0

@ HLGEM의 조언에 따라 sp_send_dbmail이 비동기식 인 경우에도 트리거에서 전자 메일을 보내지 않으려는 이유는 다음 문서를 참조하십시오. http://sqlblog.com/blogs/aaron%5Fbertrand/ 보관/2009/10/12/나쁜 습관 - 킥 - 학대 - triggers.aspx –

답변

1

로 설정 기반의 변환에 대해 생각 도움이됩니다. 방아쇠를 떨어 뜨려. Alerta_Log_Bkp 테이블에 열을 추가

ALTER TABLE dbo.Alerta_Log_Bkp ADD Alerted BIT NOT NULL DEFAULT 0; 
UPDATE dbo.Alerta_Log_Bkp SET Alerted = 1; -- so that all past entries are marked as alerted 

다음 저장 프로 시저를 만듭니다

CREATE PROCEDURE dbo.AlertOnBackupHistoryRuleViolation 
AS 
BEGIN 
    INSERT INTO [dbo].[Alerta_Log_Bkp]([Nome da Base],[Tipo]) 
    SELECT name, t = 'L' FROM sys.sysdatabases AS a 
     WHERE name NOT IN ('master','tempdb','model','BA_CMA_OM') 
     EXCEPT SELECT b.database_name, b.type from msdb..backupset AS b 
     WHERE b.backup_start_date >= DATEADD(HOUR, -2, CURRENT_TIMESTAMP) AND type = 'L' 
    UNION ALL 
    SELECT name, 'D' FROM sys.sysdatabases AS a 
     WHERE name NOT IN ('tempdb', 'model') 
     EXCEPT SELECT b.database_name, b.type FROM msdb..backupset AS b 
     WHERE b.backup_start_date >= DATEADD (day,-1, CURRENT_TIMESTAMP) AND type='D'; 

    IF @@ROWCOUNT > 0 
    BEGIN 
     DECLARE @body NVARCHAR(MAX); SET @body = N''; 

     SELECT @body = @body + CHAR(13) + CHAR(10) 
      + 'The "' + a.Tipo + '" from database "' + a.[Nome da Base] 
      + '", of the server "' + a.Servidor + '", stopped at ' 
      + COALESCE(CONVERT(VARCHAR(32), MAX(b.backup_start_date)), 'never') 
     FROM dbo.Alerta_Log_Bkp AS a LEFT OUTER JOIN msdb.dbo.backupset AS b 
     ON a.[Nome da Base] = b.database_name AND a.Tipo = b.[type] WHERE a.Alerted = 0 
     GROUP BY a.Tipo, a.[Nome da Base], a.Servidor; 

     EXEC msdb.dbo.sp_send_dbmail 
      @recipients = N'[email protected]', 
      @body   = @body, 
      @subject  = N'Problemas no Backup' , 
      @profile_name = N'PROFILE'; 

     UPDATE dbo.Alerta_Log_Bkp SET Alerted = 1 WHERE Alerted = 0; 
    END  
END 
GO 

지금 작업에서 저장 프로 시저를 호출합니다. 방아쇠를 당기지 마라.그리고 규칙을 위반하는 40 개의 데이터베이스가 있더라도 단 하나의 전자 메일 만 있습니다.

+0

Aaron 대단히 감사합니다. 스토어 프로 시저를 만들려면 SELECT @body + = CHAR (13) + CHAR (10)을 SELECT @body = CHAR (13) + CHAR (10)'로 변경해야합니다. . 또한, ";" + COALESCE (CONVERT (VARCHAR (32), MAX (b.backup_start_date)), 'never'); 그런 다음 SP를 실행했지만 하위 쿼리 오류와 같은 오류가 발생했습니다. –

+0

죄송합니다, 어떻게 든 당신이 2008 년이라고 생각했습니다. SELECT @body = @body + CHAR (13) + ... '이 (가) 수정되어야합니다. –

+0

아론, 그것은 매력처럼 일했습니다. 당신의 도움을 주셔서 대단히 감사합니다! –

1

언제 당신은 삽입하거나 스칼라 변수에 삭제 트리거가 잘못하고 다시 써야에서 쿼리의 값을 설정하는 쿼리를 작성합니다. 트리거는 한 번에 한 행이 아닌 데이터 세트에서 작동합니다. 따라서 집합 기반 논리를 사용해야합니다. 삽입 된 모든 레코드 또는 모든 배치에 대한 전자 메일을 보내시겠습니까?

트리거에서 전자 메일을 보내는 것은 좋지 않습니다. 데이터를 다른 테이블로 보낸 다음 해당 테이블을 일정 간격으로 확인하고 전자 메일을 보내도록하는 것이 좋습니다.

여기에 내 제안을 당신이

insert into #temp 
values (@base,@tipo,@servidor) 

insert into #temp 
Select "Nome da Base", tipo,servidor from inserted 
+0

아론, 빠른 답장을 보내 주셔서 감사합니다. 블로그를 읽었으며 예, 오라클에서 왔습니다. 사실, 나는 T-SQL 서면으로 만기가 전혀 없다. "select * from inserted"결과와 함께 전자 메일을 보내고 msdb에서 MAX (backup_start_date)에 대한 열을 추가하는 방법이 있습니까? 다시 감사합니다. Fabricio –

+1

왜 트리거가이 작업을 수행해야합니까? 작업이 데이터를 삽입하는 경우에도 작업이 전자 메일을 보낼 수 있습니까? –

+0

그건 의미가 있습니다. 당신은 전자 메일, 직장 내부에서 선택의 결과를 보내는 기본적인 방법에 대해 알고 있습니까? –

관련 문제