在我们的一个SQL Server数据库中,我们有许多SQL视图。一个特殊的观点每隔几周就会消失,我想知道发生了什么。
有没有办法查询SQL Server以找出何时以及谁删除了视图?
或者,可以在DROP
视图命令上添加SQL Server触发器来捕获DROP
吗?
答案 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]
数据库中删除了视图AdventureWorks
。 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 = '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
上创建的记录还要记住@Chris Pickford提到的安全性。