查找在SQL Server中删除SQL视图的人/时间

时间:2016-02-26 13:42:07

标签: sql-server

在我们的一个SQL Server数据库中,我们有许多SQL视图。一个特殊的观点每隔几周就会消失,我想知道发生了什么。

有没有办法查询SQL Server以找出何时以及谁删除了视图?

或者,可以在DROP视图命令上添加SQL Server触发器来捕获DROP吗?

4 个答案:

答案 0 :(得分: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,因此如果视图在不久前重新创建,它可能没有取证信息。

答案 1 :(得分:1)

是的,这是一个DDL触发器。有关此类触发器的MSDN文章中包含示例触发器文本。我说出于审计原因,这样的触发器是生产数据库必须的。

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

另一个技巧是使用out_list = [] for numb in('EFBO839787', 'EFBO839786', 'EFBO815155'): url = 'http://www.bbc.co.uk/sport/football/result/partial/' + numb + '?teamview=false' teams_list = [] inner_page = urllib.request.urlopen(url).read() soupb = BeautifulSoup(inner_page, 'lxml') for report in soupb.find_all('td', 'match-details'): # your code as it is for shots in soupb.find_all('td', class_='shots'): # your code as it is for incidents in soupb.find("table", class_="incidents-table").find("tbody").find_all("tr"): # your code as it is 选项创建依赖于此对象(视图)的另一个对象(视图?)。这将无法删除任何架构绑定对象依赖的对象。

答案 2 :(得分:0)

要扩展另一个答案,这里有一些代码可以开始使用DROP_VIEW的DDL触发器。举个例子,我们假设有人从[HumanResources].[vEmployee]数据库中删除了视图AdventureWorksEVENTDATA()看起来像这样:

<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 = 'You@YourDomain.com', 
    @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

答案 3 :(得分:0)

您还可以在服务器级别创建trigger,以便捕获并记录数据库中的DDL更改:

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

还要记住@Chris Pickford提到的安全性。