Does SQL Profiler work with LocalDB? - sql-server

Is it possible to use SQL Profiler to observe queries being requested of a LocalDB instance?

You can use SQL Profiler just as you do with all other SQL editions as long as you know the proper server name. You can find the server name using the SqlLocalDb utility.
To find it, use sqllocaldb info YourInstanceName to find the Instance Pipe Name. It has the form np:\\.\pipe\LOCALDB#12345\tsql\query
Use this as the server name to connect to the server and start profiling

This is what I used on SQL Server Express 2012 (note: not "LocalDB* - I have never used LocalDB so maybe that is different to a "regular" SQL Server Express).
Step 1: Setup the trace
This is basically the "hard work". You first need to find out where the default log directory of SQL Server is. You need this directory name to specfiy the trace file.
Then create a trace by doing something like this:
DECLARE #TraceID int
DECLARE #tracefile nvarchar(255)
DECLARE #endDate datetime
DECLARE #size bigint
-- no file extension!
SET #tracefile = 'C:\Data\sqlserver\MSSQL11.SQLEXPRESS\MSSQL\Log\mydb_trace'
-- tracing stops when either the max size of the file is reached
-- or the enddate (whichever occurs first)
-- size is in MB
SET #size = 250
SET #enddate = DateAdd(DAY, 15, GetDate())
EXEC #rc = sp_trace_create #TraceID output, 2, #tracefile, #size, #enddate
Now for every event that should be traced, you need to call sp_trace_setevent multiple times to define which column for that event should be returned:
For a full list of events and columns, see: http://msdn.microsoft.com/en-US/library/ms186265%28v=sql.90%29.aspx
-- Enable Event: 45 = SP:StmtCompleted
EXEC sp_trace_setevent #TraceID, 45, 27, #on -- 27: EventClass
EXEC sp_trace_setevent #TraceID, 45, 12, #on -- 12: SPID
EXEC sp_trace_setevent #TraceID, 45, 35, #on -- 35: DatabaseName
EXEC sp_trace_setevent #TraceID, 45, 11, #on -- 11: SQLSecurityLoginName
EXEC sp_trace_setevent #TraceID, 45, 6, #on -- 6: NTUserName
EXEC sp_trace_setevent #TraceID, 45, 8, #on -- 8: ClientHostName
EXEC sp_trace_setevent #TraceID, 45, 10, #on -- 10: ApplicationName
EXEC sp_trace_setevent #TraceID, 45, 1, #on -- 1: TextData
EXEC sp_trace_setevent #TraceID, 45, 13, #on -- 13: Duration
EXEC sp_trace_setevent #TraceID, 45, 14, #on -- 14: StartTime
EXEC sp_trace_setevent #TraceID, 45, 15, #on -- 15: EndTime
EXEC sp_trace_setevent #TraceID, 45, 18, #on -- 18: CPU
EXEC sp_trace_setevent #TraceID, 45, 29, #on -- 29: Nesting Level
All of the above calls must be done for each and every event you want to trace!
I find the events 12 = SQL:BatchCompleted, 42 = SP:Starting, 43 = SP:Completed, 45 = SP:StmtCompleted, 50 = SQL Transaction the most interesting ones.
Optionally you can setup a filter, I usually filter out system events and only show events for a specific database:
-- Exclude system events (so only user events are shown)
-- 60: IsSystem Column
-- 0: logical Operator: AND (only)
-- 1: comparison operator: not equal
-- 1: value
EXEC sp_trace_setfilter #TraceID, 60, 0, 1, 1
-- only mydb database
EXEC sp_trace_setfilter #TraceID, 35, 0, 6, N'mydb'
Once the trace is setup, it must be activated:
EXEC sp_trace_setstatus #TraceID, 1
(Note the above must be run as a single batch, because of the variable usage).
To see how the trace was defined, you can use the following statement:
select traceid,
case property
when 1 then 'Trace Options'
when 2 then 'Trace file'
when 3 then 'Max. file size'
when 4 then 'Stop time'
when 5 then 'Status'
end as property_name,
case
when property = 5 then
case convert(nvarchar(max), value)
when '1' then 'Active'
else 'Inactive'
end
else convert(nvarchar(max), value)
end as value
from ::fn_trace_getinfo(null)
where property in (2,3,5)
Now run your application or whatever issues statements to the database that you want to trace.
Step 2: Retrieve trace information
For this you need to know the full path to the actual trace file (from Step 1). Note that for fn_trace_gettable you need to specify the file including the file extension.
SELECT ApplicationName,
LoginName,
HostName,
SPID,
Duration,
StartTime,
EndTime,
DatabaseName,
reads,
writes,
RowCounts,
cpu,
EventClass,
case EventClass
when 10 then 'RPC:Completed'
when 11 then 'RPC:Starting'
when 12 then 'SQL:BatchCompleted'
when 13 then 'SQL:BatchStarting'
when 40 then 'SQL:StmtStarting'
when 41 then 'SQL:StmtCompleted'
when 42 then 'SP:Starting'
when 43 then 'SP:Completed'
when 44 then 'SP:StmtStarting'
when 45 then 'SP:StmtCompleted'
when 50 then 'SQL Transaction'
when 67 then 'Execution Warnings'
when 71 then 'Prepare SQL'
when 72 then 'Exec Prepared SQL'
when 73 then 'Unprepare SQL'
end as Event,
LineNumber,
TextData
FROM ::fn_trace_gettable('C:\Data\sqlserver\MSSQL11.SQLEXPRESS\MSSQL\Log\mydb_trace.log', default)
order by StartTime;
Adjust the above to return the information you are interested in.
Once you have the information you need, you have to turn off the trace:
Step 3: disable the trace
For this you need to know the Trace-ID (e.g. by running the "info statement from Step 1). The with this ID, you need to first stop the trace, then you can delete it:
-- stop the trace
EXEC sp_trace_setstatus #TraceID, 0
-- delete the trace
EXEC sp_trace_setstatus #TraceID, 2

From http://expressprofiler.codeplex.com/
ExpressProfiler (aka SqlExpress Profiler) is a simple but good enough replacement for SQL Server Profiler with basic GUI.
No requirements, no installation.
Can be used with both Express and non-Express editions of SQL Server 2005/2008/2008r2/2012 (including LocalDB)

It as simple as setting the server to (LocalDB)\v11.0
http://expressprofiler.codeplex.com/discussions/456518

Microsoft SQL Server 2012 Express LocalDB is an execution mode of SQL Server Express targeted to program developers.
Sql Profiler is not provided with SQL Server Express.
Thus, you can't use Sql profiler for your LocalDB.
However,you can go through alternative ways.
How to use SQL Profiler with SQL Server Express Edition

I had the same issue and following solution worked for me. Open the SQL profiler and connect to the sql server. In the new trace select event selection tab. Then check the show all events check box. After that, from the list select the checkboxes under data base name. Now use column filter then select databasename. Select like and type %localDB%. then start the trace. It will capture every thing on that database.

Related

Creating an SSRS report identifying database activity

I'm trying to create a SQL query that tells if any new tables/views or SP's have been created for a particular month. So far getting the info on any new objects created has been the easy part
select SCHEMA_NAME(schema_id) AS schema_name,
name AS objects_name,
create_date,
modify_date,
type,
so.type_desc,
principal_id
from sys.objects so
where type in ('U','V','P')
and create_date > DATEADD(DAY, -30, CURRENT_TIMESTAMP)
What has been challenging is finding out who created or modified these artefacts. All online sources point to me having to create a trigger on the DB. Is there any query I can run to identify the responsible person.
NB:not the roles but the actual userid
Tried a bunch of queries including a trace:
DECLARE #RC int, #TraceID int, #on BIT
EXEC #rc = sp_trace_create #TraceID output, 2, N'C:\path\file'
SELECT RC = #RC, TraceID = #TraceID
-- Follow Common SQL trace event list and common sql trace
-- tables to define which events and table you want to capture
SELECT #on = 1
EXEC sp_trace_setevent #TraceID, 128, 1, #on
-- (128-Event Audit Database Management Event, 1-TextData table column)
EXEC sp_trace_setevent #TraceID, 128, 11, #on
EXEC sp_trace_setevent #TraceID, 128, 14, #on
EXEC sp_trace_setevent #TraceID, 128, 35, #on
EXEC #RC = sp_trace_setstatus #TraceID, 1
GO

SQL Server returns error with sp_trace_generateevent

I get an error from one of my databases when trying to execute this one
create or alter procedure [dbo].[test_sp]
with execute as owner
as
SELECT SUSER_SNAME()+ ' '+ USER_NAME();
begin
exec master..sp_trace_generateevent #eventid = 82 ,
#userinfo=N'test'
end
GO
exec [dbo].[test_sp]
Error:
Msg 8189, Level 14, State 10, Procedure master..sp_trace_generateevent, Line 1 [Batch Start Line 9]
You do not have permission to run 'SP_TRACE_GENERATEEVENT'.
Granted ALTER TRACE to my user (which returns in SUSER_SNAME()), but it wasn't help
The same script on the second database (same server) works without errors.
What else can it be?
You're trying to run this with EXECUTE AS OWNER, and the owner is a database-level principal and you can't operate outside the current database while impersonating a database-level principal. Switch to EXECUTE AS CALLER (the default) to have the caller's identity used to run the proc in master. eg
create or alter procedure [dbo].[test_sp]
with execute as caller
as
SELECT SUSER_SNAME()+ ' '+ USER_NAME();
begin
exec master..sp_trace_generateevent #eventid = 82, #userinfo = N'test'
end
GO
exec [dbo].[test_sp]
This can be made to work with owner-impersonation by marking the database as TRUSTWORTHY. See: Extending Database Impersonation by Using EXECUTE AS and Guidelines for using the TRUSTWORTHY database setting in SQL Server

Setting SQL Server compatibility level based on the server in script

When I try to set the compatibility level for SQL Server in a script it errors out for SQL Server 2008. I want this script to be same to executed against all the servers - 2008, 2012 or 2014 which we currently support.
-- Set database compatibility --
IF SUBSTRING(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR),1 ,2) >= 11
BEGIN
RAISERROR ('sql server 12 and above', 10, 1)
ALTER DATABASE JJAI_TESTDB SET COMPATIBILITY_LEVEL = 110
END
ELSE
BEGIN
RAISERROR ('sql server 2008',10, 1)
ALTER DATABASE JJAI_TESTDB SET COMPATIBILITY_LEVEL = 100
END
GO
Below is the error:
Msg 15048, Level 16, State 1, Line 5
Valid values of the database compatibility level are 80, 90, or 100.
Okay, I was able to do it by executing the alter statement within an execute statement like below.
/* Set database compatibility */
IF SUBSTRING(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR),1 ,2) >= 11
EXECUTE ('ALTER DATABASE $(DATABASENAME) SET COMPATIBILITY_LEVEL = 110')
ELSE
EXECUTE ('ALTER DATABASE $(DATABASENAME) SET COMPATIBILITY_LEVEL = 100')
GO

Why am I getting different results for 2008 sql server and 2014 while tracing "Audit Add Member to DB Role Event"?

I have two sql servers: 2008 and 2014.
When I am trying to collect traces for "Audit Add Member to DB Role" event class, my 2008 server does not capture TextData, but 2014 does capture. But there is no information on msdn about TextData for this event class:
Audit Add Member to DB Role Event Class
Code to create traces:
DECLARE #TraceID int
DECLARE #FILESIZE bigint
set #FILESIZE = 5
DECLARE #FILEPATH nvarchar(256)
SET #FILEPATH = 'C:\Temp\Traces\trace'
DECLARE #StopTime datetime
Set #StopTime = DATEADD( dd, 7, GETDATE())
exec sp_trace_create #TraceId=#TraceID OUT, #options=2, #tracefile=#FILEPATH, #maxfilesize=#FILESIZE, #stoptime=#StopTime
exec sp_trace_setevent #TraceID=#TraceID,#EventId=110,#ColumnId=1,#on=1
exec sp_trace_setstatus #traceid = #TraceID, #status = 1
Where
#EventId=110 - Audit Add Member to DB Role Event Class
#ColumnId=1 - TextData column.
When I execute:
exec sp_addrolemember 'db_accessadmin', 'TESTPC\TestGroup'
exec sp_droprolemember 'db_accessadmin', 'TESTPC\TestGroup'
I am getting results:
For 2008:
For 2014:
Is there any docs that I cant find on the web?

How to get sum of amount of all databases together through cursor

I am stucking in one place in sql query. I have 20 databases and all database's table name and columns name are same but data is different. I am creating a sql query to get payment amount of particular date from all databases together.
I have many columns in payment table. I need on sum(amount) regarding there paymentTypeID column because I can get amount on the basis of paymentTypeID. All paymentTypeIDs are different in databases but sometimes it is same. I have created a cursor for this.
My code is:
create table #tmpDBs(DBName varchar(255), CurrentDayPaymentAmount float)
declare cDBs cursor for
select name from master.dbo.sysdatabases
declare #DB varchar(255)
open cDBs
fetch next from cDBs into #DB
while ##fetch_status = 0
begin
exec('
declare #DateCurrent datetime
set #DateCurrent = '{Current Date}'
insert into #tmpDBs
select DBName = ' + #DB + ',
CurrentDayPaymentAmount = (select sum(p.amount) from ' + #DB + '.dbo.Payment p where p.eDate between #DateCurrent and dateadd(day, 1, #DateCurrent) and (p.paymenttypeid in (14, 15, 16, 17, 21, 22, 24, 35, 37, 38, 50)))
')
fetch next from cDBs into #DB
end
close cDBs
deallocate cDBs
select * from #tmpDBs
drop table #tmpDBs
I used In clause to pass all databases paymenttypeid together.
This code is for retrieve the payment amount from 2 databases. paymenttypeid 14, 15, 16,17, 22, 24, 38 is for first database and 21, 35, 37, 50 is for second database. My problem is that when I put these paymentTypeID in In clause it adds the amount of matching paymenttypeid of other database.
For example if first database actual amount is 4589$ but it adds additional amount say 5469$ by using second database paymenttypeid. If I pass only one database paymenttypeid it shows the correct amount.
What is the issue in my query.
I think you explained the issue yourself: you want only types 1, 2 and 3 from DB1 and only types 4, 5 and 6 from DB2, but your query doesn't do that, it asks for types 1, 2, 3, 4, 5 and 6 from DB1 and DB2.
That means you need to use a different WHERE clause for each databases, depending on which types you want. So how do you know which types you want from each database and how can you express that logic in your stored procedure?
As a completely different solution, create a view in each database with the correct WHERE clause and then just query the view for your report.

Resources