How to determine who performed DROP/DELETE on Sql Server database objects? - sql-server

There is always a need to find out details, either intentionally Or mistakenly someone executed DROP/DELETE command on any of following SQL Server database objects.
DROPPED - Table from your database
DROPPED - Stored Procedure from your database
DELETED - Rows from your database table
Q. Is there TSQL available to find db user who performed DELETE/DROP?
Q. What kind of permissions are needed for user to find out these details?

Did you check this ?
Right click on database.
Go to as shown in image :
Solution 2 :
This query gives alot of useful information for a database(apply filter as required) :
DECLARE #filename VARCHAR(255)
SELECT #FileName = SUBSTRING(path, 0, LEN(path)-CHARINDEX('\', REVERSE(path))+1) + '\Log.trc'
FROM sys.traces
WHERE is_default = 1;
SELECT gt.HostName,
gt.ApplicationName,
gt.NTUserName,
gt.NTDomainName,
gt.LoginName,
--gt.SPID,
-- gt.EventClass,
te.Name AS EventName,
--gt.EventSubClass,
-- gt.TEXTData,
gt.StartTime,
gt.EndTime,
gt.ObjectName,
gt.DatabaseName,
gt.FileName,
gt.IsSystem
FROM [fn_trace_gettable](#filename, DEFAULT) gt
JOIN sys.trace_events te ON gt.EventClass = te.trace_event_id
WHERE EventClass in (164) --AND gt.EventSubClass = 2
ORDER BY StartTime DESC;

Related

Find out when the last failover occurred in AlwaysOn availability groups

I used below metioned query to find out if any failover happened in the last 30 minutes
create table #errormsg(duration datetime,errornum int,dbmessage varchar(max))
DECLARE #tags3 VARCHAR(5000)SET #tags3 = (SELECT CAST( t.target_data AS XML ).value('(EventFileTarget/File/#name)[1]', 'VARCHAR(MAX)') FROM sys.dm_xe_sessions s INNER JOIN sys.dm_xe_session_targets t ON s.address = t.event_session_address WHERE t.target_name = 'event_file' and s.name='AlwaysOn_health');
IF #tags3 is Not NULL begin WITH cte_HADR AS (SELECT object_name, CONVERT(XML, event_data) AS data FROM sys.fn_xe_file_target_read_file(#tags3, null, null, null)WHERE object_name = 'error_reported')
insert into #errormsg SELECT data.value('(/event/#timestamp)[1]','datetime')AS [timestamp],data.value('(/event/data[#name=''error_number''])[1]','int') AS [error_number],data.value('(/event/data[#name=''message''])[1]','varchar(max)') AS [message] FROM cte_HADR WHERE data.value('(/event/data[#name=''error_number''])[1]','int') = 1480 select distinct GETDATE() as currenttime, er.duration,dbs.name from #errormsg er inner join sys.databases dbs on er.dbmessage LIKE '%"' +dbs.name+'"%' where er.duration>=(DATEADD(mi,-30,GETDATE()) );
drop table #errormsg;end
else IF OBJECT_ID(N'TempDB.dbo.#errormsg', N'U') IS NOT NULL drop table #errormsg;
But I did not get the result I was expecting because of the "Incorrect Timestamp on Events in Extended Events".
In SSMS -->Management-->Extended Events-->Sessions-->AlwaysOn_health--> click event file.
In that event file,
I checked recently role changed time for 'availablity_replica_state_change'.
In MSSQL log folder--> availablity_replica_state_change time in "AlwaysOn_health" file
timestamp in (1) and (2) needs to be same.
But for me its shows different time. So I didn't get the proper result.
Instead of using extended events, Is there any query to read the MS SQL error logs?
Is there any query to find out if any failover happened in the last 30 minutes?
Please help me to find a solution for this .

Why SQL SERVER 2008 Suddenly change to SINGLE USER from MULTI USER

My production database suddenly changed to single user model.
I changed it back to MULTI USER and now everything is running normally.
Why did this happen?
A database doesn't just get set to single user by itself, there should be some process or person actually issued the command to happened the same.
That ALTER DATABASE command counts as a DDL operation, and it thus logged in the Default Trace.
you can see some quick investigation info from the Schema Changes history Report, or query the default trace directly:
--SELECT * from sys.traces
declare #TraceIDToReview int
declare #path varchar(255)
SET #TraceIDToReview = 1 --this is the trace you want to review!
SELECT #path = path from sys.traces WHERE id = #TraceIDToReview
SELECT
TE.name As EventClassDescrip,
v.subclass_name As EventSubClassDescrip,
T.*
FROM ::fn_trace_gettable(#path, default) T
LEFT OUTER JOIN sys.trace_events TE ON T.EventClass = TE.trace_event_id
LEFT OUTER JOIN sys.trace_subclass_values V
ON T.EventClass = V.trace_event_id AND T.EventSubClass = V.subclass_value
WHERE DatabaseName ='Blank'
AND IndexID = 15 --Single User
OR IndexID = 16 --Multi User

MSSQL: How to get statistics of reading of table?

Is there a way to get the amount of 'selects' from a mssql table?
I mean without rewriting application to log every request or without parsing sql profile logs...
Is there any build-in tool (sql request)?
SQL Server maintains index usage statistics since last restart. You can use user_reads column from query bellow to get wanted statistics:
SELECT OBJECT_NAME(ddius.[object_id], ddius.database_id) AS [object_name] ,
ddius.index_id ,
ddius.user_seeks ,
ddius.user_scans ,
ddius.user_lookups ,
ddius.user_seeks + ddius.user_scans + ddius.user_lookups
AS user_reads ,
ddius.user_updates AS user_writes ,
ddius.last_user_scan ,
ddius.last_user_update
FROM sys.dm_db_index_usage_stats ddius
WHERE ddius.database_id > 4 -- filter out system tables
AND OBJECTPROPERTY(ddius.OBJECT_ID, 'IsUserTable') = 1
AND ddius.index_id > 0 -- filter out heaps
AND database_id = DB_ID()
ORDER BY user_reads DESC

Recently created index in SQL Server

How to find recently created index details in my SQL Server database? Any query to find this?
In my database there are a lot of indexes. I want to know which of those indexes were recently created, with all their details.
You can use SCHEMA changes history to know index creation changes along with many changes
Below is how you do it..
1.Right click server
2.Goto reports -->standard reports-->Schema changes history
below is screenshot from mt device
Default trace is enabled by default,unless you turn it on
below query tells you,if default trace status is ON
select * from sys.configurations where name like '%trace%'
below query can provide object creation stats
SELECT OBJECT_NAME(objectid),objectname,indexid
FROM sys.fn_trace_gettable(CONVERT(VARCHAR(150), ( SELECT TOP 1
f.[value]
FROM sys.fn_trace_getinfo(NULL) f
WHERE f.property = 2
)), DEFAULT) T
JOIN sys.trace_events TE ON T.EventClass = TE.trace_event_id
where DatabaseName=db_name()
ORDER BY t.StartTime ;

How to check if SQL Server Tables are System Tables

Using the stored procedure sp_msforeachtable it's possible to execute a script for all tables in a database.
However, there are system tables which I'd like to exclude from that. Instinctively, I would check the properties IsSystemTable or IsMSShipped. These don't work like I expect - I have for example a table called __RefactorLog:
But when I query if this is a system or MS Shipped table, SQL Server reports none of my tables are system tables:
exec (N'EXEC Database..sp_msforeachtable "PRINT ''? = '' + CAST(ObjectProperty(Object_ID(''?''), ''IsSystemTable'') AS VARCHAR(MAX))"') AS LOGIN = 'MyETLUser'
-- Results of IsSystemTable:
[dbo].[__RefactorLog] = 0
[schema].[myUserTable] = 0
and
exec (N'EXEC Database..sp_msforeachtable "PRINT ''? = '' + CAST(ObjectProperty(Object_ID(''?''), ''IsMSShipped'') AS VARCHAR(MAX))"') AS LOGIN = 'MyETLUser'
-- Results of IsMSShipped:
[dbo].[__RefactorLog] = 0
[schema].[myUserTable] = 0
When I look into the properties of the table (inside SSMS), the table is marked as a system object. An object property like IsSystemObject doesn't exist though (AFAIK).
How do I check if a table is a system object, apart from the object property? How does SSMS check if a table is a system object?
Management studio 2008 seems to run some quite ugly following code when opening the "System Tables" folder in the object explorer, the key bit seems to be:
CAST(
case
when tbl.is_ms_shipped = 1 then 1
when (
select
major_id
from
sys.extended_properties
where
major_id = tbl.object_id and
minor_id = 0 and
class = 1 and
name = N''microsoft_database_tools_support'')
is not null then 1
else 0
end
AS bit) AS [IsSystemObject]
(Where tbl is an alias for sys.tables)
So it seems that it's a combination - either is_ms_shipped from sys.tables being 1, or having a particular extended property set.
__refactorlog is, in contrast to what SSMS suggests, a user table. It is used during deployment to track schema changes that cannot be deduced from the current database state, for example renaming a table.
If all your other user tables are in a custom (non-dbo) schema, you can use a combination of the isMSshipped/isSystemTable attributes and the schema name to decide if a table is 'in scope' for your script.
In the past I've worked on the assumption that, in the sys.objects table, column is_ms_shipped indicates whether an object is or is not a system object. (This column gets inherited by other system tables, such as sys.tables.)
This flag can be set by procedure sp_ms_markSystemObject. This, however, is an undocumented procedure, is not supported by Microsoft, I don't think we're supposed to know about it, so I didn't tell you about it.
Am I missing something?
However, there are system tables which I'd like to exclude from that
At least on SQL Server 2008, sp_MSforeachtable already excludes system tables, as this excerpt from it shows:
+ N' where OBJECTPROPERTY(o.id, N''IsUserTable'') = 1 ' + N' and o.category & ' + #mscat + N' = 0 '

Resources