Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 查找SQL Server中删除SQL视图的人员/时间_Sql Server - Fatal编程技术网

Sql server 查找SQL Server中删除SQL视图的人员/时间

Sql server 查找SQL Server中删除SQL视图的人员/时间,sql-server,Sql Server,在我们的一个SQL Server数据库中,我们有许多SQL视图。每隔几周就有一个特定的视图消失,我想知道发生了什么 是否有一种方法可以查询SQL Server以找出何时以及谁删除了该视图 或者,是否可以在DROPview命令上添加SQL Server触发器以捕获DROP,并使其失败?是的,这是一个DDL触发器。MSDN文章中包含了关于此类触发器的示例触发器文本。我想说,出于审计的原因,这样的触发器是生产数据库上必须的 另一个技巧是使用SCHEMA\u BINDING选项创建依赖于此对象(视图)

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

是否有一种方法可以查询SQL Server以找出何时以及谁删除了该视图


或者,是否可以在
DROP
view命令上添加SQL Server触发器以捕获
DROP
,并使其失败?

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


另一个技巧是使用
SCHEMA\u BINDING
选项创建依赖于此对象(视图)的另一个对象(视图?)。这将使得无法删除任何对象架构绑定的对象所依赖的对象。

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


另一个技巧是使用
SCHEMA\u BINDING
选项创建依赖于此对象(视图)的另一个对象(视图?)。这将使得无法删除任何对象模式绑定对象所依赖的对象。

此信息将写入默认跟踪。下面是一个收集信息的查询示例

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,因此如果不久前重新创建视图,它可能没有法医信息。

此信息将写入默认跟踪。下面是一个收集信息的查询示例

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的滚动跟踪,因此如果不久前重新创建了视图,它可能没有法医信息。

要扩展另一个答案,下面是一些代码,用于
DROP\u 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>

为了扩展另一个答案,下面是一些代码,可以从
DROP\u 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>
您还可以在服务器级别创建一个数据库,以便捕获和记录数据库上的更改:

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
你可以在这里找到更多信息

如果从数据库中删除对象,您将看到在表AuditDatabaseObject上创建的记录

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

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

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
你可以在这里找到更多信息

如果从数据库中删除对象,您将看到在表AuditDatabaseObject上创建的记录


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

问问自己,“谁需要能够删除数据库对象?”。将对数据库的权限限制为这些人/帐户。我正是为此目的启动了一项服务。问问自己,“谁需要能够删除数据库对象?”。将对数据库的权限限制为这些人/帐户。我正是为此目的启动了一项服务。谢谢,这使我更进一步。查询显示该视图在几天前被删除,并且是通过哪个登录名和哪个应用程序删除的。谢谢,这让我更进一步。该查询显示该视图在几天前被删除,以及由哪个登录名和哪个应用程序删除。