2016-02-26 86 views
0

在我們的一個SQL Server數據庫中,我們有很多SQL視圖。一個特定的觀點每隔幾個星期就會消失,我想知道發生了什麼。查找SQL Server中SQL視圖被刪除的人員/時間

有沒有辦法查詢SQL Server來找出何時和誰刪除視圖?

或者,是否可以在DROP視圖命令中添加SQL Server觸發器以捕獲並失敗DROP

+1

問自己一個問題,「誰需要能夠刪除數據庫對象?」。限制你的數據庫對這些人/帳戶的權限。 –

+0

我爲此開始了一項服務[dbhistory.com](http://dbhistory.com)。 –

回答

1

是的,這是一個DDL觸發器。 MSDN文章中包含有關此類觸發器的示例觸發器文本。出於審計原因,我認爲這樣的觸發器是生產數據庫中的必需品。

https://technet.microsoft.com/en-us/library/ms187909.aspx

另一個技巧是創建依賴這個對象(視圖)另一個對象(圖?)和SCHEMA_BINDING選項上。這將使不可能放棄任何對象架構綁定對象依賴。

4

將此信息寫入默認跟蹤。以下是收集信息的示例查詢。

SELECT 
    te.name 
    ,tt.DatabaseName 
    ,tt.StartTime 
    ,tt.HostName 
    ,tt.LoginName 
    ,tt.ApplicationName 
    ,tt.LoginName 
FROM sys.traces AS t 
CROSS APPLY fn_trace_gettable(
    --get trace folder and add base file name log.trc 
    REVERSE(SUBSTRING(REVERSE(t.path), CHARINDEX(N'\', REVERSE(t.path)), 128)) + 'log.trc', default) AS tt 
JOIN sys.trace_events AS te ON 
    te.trace_event_id = tt.EventClass 
JOIN sys.trace_subclass_values AS tesv ON 
    tesv.trace_event_id = tt.EventClass 
    AND tesv.subclass_value = tt.EventSubClass 
WHERE 
    t.is_default = 1 --default trace 
    AND tt.ObjectName = N'YourView' 
    AND tt.DatabaseName = N'YourDatabase'; 

注意默認跟蹤是保持最大100MB,因此它可能沒有法醫的信息,如果該觀點在不久前重新翻滾的痕跡。

+0

謝謝,這讓我更靠近了一步。該查詢顯示該視圖在幾天前被刪除,並通過哪個登錄和哪個應用程序。 –

0

要展開另一個答案,下面是一些代碼,以便開始使用DROP_VIEW的DDL觸發器。舉一個例子,假設有人從AdventureWorks數據庫中刪除了視圖[HumanResources].[vEmployee]。該EVENTDATA()會是這個樣子:

<EVENT_INSTANCE> 
    <EventType>DROP_VIEW</EventType> 
    <PostTime>2016-02-26T09:02:58.190</PostTime> 
    <SPID>60</SPID> 
    <ServerName>YourSqlHost\SQLEXPRESS</ServerName> 
    <LoginName>YourDomain\SomeLogin</LoginName> 
    <UserName>dbo</UserName> 
    <DatabaseName>AdventureWorks2012</DatabaseName> 
    <SchemaName>HumanResources</SchemaName> 
    <ObjectName>vEmployee</ObjectName> 
    <ObjectType>VIEW</ObjectType> 
    <TSQLCommand> 
    <SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" /> 
    <CommandText>DROP VIEW [HumanResources].[vEmployee] 
</CommandText> 
    </TSQLCommand> 
</EVENT_INSTANCE> 

這裏是一個可能的DDL觸發器聲明:

CREATE TRIGGER trgDropView 
ON DATABASE 
FOR DROP_VIEW 
AS 
BEGIN 

--Grab some pertinent items from EVENTDATA() 
DECLARE @LoginName NVARCHAR(MAX) = EVENTDATA().value('(/EVENT_INSTANCE/LoginName)[1]', 'NVARCHAR(MAX)') 
DECLARE @TsqlCmd NVARCHAR(MAX) = EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)') 

--Now do something. Lots of possibilities. Here are two: 

--1) Send Email 
DECLARE @Subj NVARCHAR(255) = @@SERVERNAME + ' - VIEW DROPPED' 
DECLARE @MsgBody NVARCHAR(255) = 'Login Name: ' + @LoginName + CHAR(13) + CHAR(10) + 
    'Command: ' + @TsqlCmd 
EXEC msdb..sp_send_dbmail 
    @recipients = '[email protected]', 
    @subject = @Subj, 
    @body = @MsgBody 

--2) Log an error 
DECLARE @ErrMsg NVARCHAR(MAX) = @@SERVERNAME + ' - VIEW DROPPED' + CHAR(13) + CHAR(10) + 
    'Login Name: ' + @LoginName + CHAR(13) + CHAR(10) + 
    'Command: ' + @TsqlCmd 
RAISERROR(@ErrMsg, 16, 1) WITH LOG; 

END 
0

你也可以爲了捕捉和記錄DDL變化創造trigger在服務器級別數據庫:

CREATE TRIGGER [Trg_AuditStoredProcedures_Data] 
ON ALL SERVER 
FOR  CREATE_PROCEDURE,ALTER_PROCEDURE,DROP_PROCEDURE,CREATE_TABLE,ALTER_TABLE, 
DROP_TABLE,CREATE_FUNCTION,ALTER_FUNCTION,DROP_FUNCTION,CREATE_VIEW,ALTER_VI EW, 
DROP_VIEW,CREATE_DATABASE,DROP_DATABASE,ALTER_DATABASE, 
CREATE_TRIGGER,DROP_TRIGGER,ALTER_TRIGGER 

AS 


SET ANSI_PADDING ON 

DECLARE @eventdata XML; 
SET @eventdata = EVENTDATA(); 

SET NOCOUNT ON 


/*Create table AuditDatabaseObject in order to have a history tracking for every DDL change on the database*/ 
INSERT INTO AuditDatabaseObject 
(DatabaseName,ObjectName,LoginName,ChangeDate,EventType,EventDataXml,HostName) 
VALUES (
    @eventdata.value('(/EVENT_INSTANCE/DatabaseName)[1]','sysname') 
, @eventdata.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname') 
, @eventdata.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname') 
, GETDATE() 
, @eventdata.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname') 
, @eventdata 
, HOST_NAME() 
); 

DECLARE @Valor VARCHAR(30),@EvenType VARCHAR(30) 
SET @Valor = @eventdata.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname') 
SET @EvenType = @eventdata.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname') 

IF (IS_SRVROLEMEMBER('sysadmin',@Valor) != 1 AND @EvenType = 'DROP_DATABASE') 
BEGIN 
    ROLLBACK 
END 

,你可以在這裏找到更多的信息EVENTDATA()

如果一個對象被從數據庫中刪除,你會看到在桌子上創造了一項紀錄AuditDatabaseObject

enter image description here

也牢記安全爲@克里斯·皮克福德提及。