I need to identify and be notified when records in my SQL Server 2012 database table meet a specific condition. For example, when a record in the trans_record table has any entries in the “status” column of “error”.
The query is simple enough and I have setup an SSIS package to query the table with the appropriate “where” clause. I followed this with a SQL Agent job to run the SSIS package daily at 7:00am and export the offending records to a flat text file.
What I need to understand is how I can be emailed only when a record is found with the query performed by the SSIS package. It appears that the SSIS package will always create a file regardless if any records are found.
I see that SQL Server supports Alerts and defined Operators to be notified, but I don’t understand how to be notified only if my query returns a valid record.
How can I set this up in SQL Server?
Thanks
If I understand correctly, you would like to be emailed by SSIS only when there is a record in the table with a status of error. If this is correct then you can achieve this from SSIS package.
If you would like to query the database and send an email, then you will require two Tasks and two connections:
Execute SQL task
Send Email Task
Database Connection
Email connection
Configure connections with relevant database connection details and exchange details for email connection.
Add the connections to the tasks, create Precedence Constraint from the Exec SQL to Send Email task.
In the Exec SQL create query or use stored procedure to return false or true if the record exists, or if you prefer count of the records in the table.
Return the outcome of the query to the variable (SSIS variable, you will have to add it in the package). Change the settings on the Precedence Constraint to add evaluation of expression and use your variable i.e. if you set the variable to be #recordPresent then the evaluation will be #recordPresent==true (if the value returned is false or true) or #recordPresent > 0 (if the variables contains the count of records).
If the expression evaluates to true and constraint is of the type requiered i.e. success, completion, failed the control will be passed to the next task in this case Email. If Send an email task is set correctly (from, to, subject and Body of the email as well as exchange connection string is correct), email will only be sent when there is a record in the table.
I hope this helps.
Related
How to let an Execute SQL SSIS component decide whether to continue package execution, based on whether a specific SQL Agent job is running.
This is an easy way of letting the package decide to proceed based on whether a specific SQL Agent job is running at the time the package is invoked.
To do so:
Create an Execute SQL task component at the start of your package.
Give it a query that will ask [msdb] on the execution status of the SQL Agent job you are interested in.
Like so:
USE [msdb];
SELECT ISNULL(MAX([sj].[name]),'') AS [JobRunning]
FROM [msdb].[dbo].[sysjobactivity] AS [sja]
INNER JOIN [msdb].[dbo].[sysjobs] AS [sj]
ON [sja].[job_id] = [sj].[job_id]
WHERE [sja].[start_execution_date] IS NOT NULL
AND [sja].[stop_execution_date] IS NULL
AND CAST([sja].[start_execution_date] AS DATE) = CAST(GETDATE() AS DATE)
AND ISNULL([sj].[name],'') LIKE '%NameOfSQLAgentJobThatNeedsToNotBeRunnimg%';
And as shown in the screenshot:
Make sure to set the result set property to single row and to create a Package scoped variable to hold the returned value.
Like so:
And then you need to add the fist step of the Package logic whatever that might be and connect the two.
When you have connected the two, edit the Precedence Constraint and set it to Expression and Constraint and upon Success set the code to:
#[User::JobRunning]!="NameOfSQLAgentJobThatNeedsToNotBeRunnimg"
like so:
And that's it.
Save, build, deploy :)
I am frequently testing certain areas on a development server and so running a pre-defined SQL statement to truncate the tables in question before testing again. It would only be a slip of a key to switch to the live server.
I'm looking for an IF statement or similar to prevent that.
Either to check the server name, database name, or even that a certain record in a different table exists before running the query.
Any help appreciated
For such cases I use stored procedures. I'd call them TestTruncateTables, etc.
Then instead of calling TRUNCATE TABLE you should CALL TestTruncateTables.
Just make sure that the procedures are not created on the live server. If by any chance you happen to run CALL TestTruncateTables on the live server you only get an error about non-existing proc.
I have a SQL Server 2000 database with a stored procedure that deletes a row from a specific table, given its id. When I call the stored procedure from VB.NET, it does not delete the row, but running the same script directly on the database via SSMS, it works.
Here's my chain of events:
Start SQL Server Profiler to watch all calls to the database. I have
it setup to track when stored procedure starts, completes, and even
on SQL statements start/complete within that stored procedure.
Call stored procedure via VB.NET dll.
Stop the profiler trace to avoid excessive data to dig through.
Select from table, and see that the row still exists.
View the profiler trace, which only shows RPC:Starting, SP:Starting, RPC:Completed. No inner statements are traced, which verifies why the row wasn't deleted since the delete statement never fired.
Copy/paste the EXEC call directly from the RPC:Starting trace entry from when it was called via VB.NET, into SQL Server Management Studio query window pointed to the same database with same credentials.
Start profiler again.
Execute EXEC statement from bullet 6 in SSMS.
Stop profiler.
Select from table, and see that the row GOT DELETED like it should.
View the profiler trace, which shows SP:Starting, all statements starting/completed including the DELETE statement, and SP:Completed.
Why would running it via RPC make it not execute any of the statements in the proc, but running directly acts as it should?
EDIT: Below is my VB.NET code. This is the same code we use in over 100 other places:
Dim paramRowID As New SqlParameter("#RowID", sRowID)
Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteNonQuery(oConn, "spDeleteRow", paramRowID)
See SqlHelper source here.
EDIT: I hate myself right now. :) SQL threw an exception "nvarchar is incompatible with image" about another parameter that I was passing NULL to. SSMS didn't worry about the type, but VB.NET did since I didn't explicitly tell it that it was of type image. Once I defined that param, it worked. I wish profiler would have told me there was an error though.
Any help would be appreciated,
Greg
That would be because SSMS does not call an RPC but a batch. There is no way in fact to call a RPC from SSMS since you cannot declare a parameter, which is what differentiate an RPC call from a batch call in TDS:
2.2.1.3 SQL Batch To send a SQL statement or a batch of SQL statements, the SQL batch, represented by a Unicode string, is copied into the data section of a TDS packet and then sent to the database server that supports SQL. A SQL batch may span more than one TDS packet. See section 2.2.6.6 for additional detail
2.2.1.5 Remote Procedure Call To execute a remote procedure call (RPC) on the server, the client sends an RPC message data stream to the server. This is a binary stream that contains the RPC name or numeric identifier, options, and parameters. RPCs MUST be in a separate TDS message and not intermixed with SQL statements. There can be several RPCs in one message. See section 2.2.6.5 for additional details.
So monitor instead for the SQL:BatchCompleted event and you'll see your SSMS statement(s).
Does the user the application is using to connect to sql have permission to execute stored procedures? That is the first thing I would verify.
I have a database view that gathers about 10 member names a day, based on when they joined.
I want to setup something where these people will automatically be emailed an html page
i have made.
and repeat this daily, at first i was going to build an asp.net page
where i would pull the view and loop through the email addresses, but i wanted to see if it was possible to do this soley in sql server 2005
Could i use a trigger or a stored procedure or i havent really used sql server agent
sp_send_dbmail as the others said is what you use to send the E-mail
To set it up to E-mail daily you can use a SQL Server Agent Job
In SSMS, connect to your server, then open SQL Server Agen->Jobs
In here you can set up the steps for your job and the frequency with which it runs.
You can use sp_send_dbmail to send email directly from SQL Server, assuming you've set up Database Mail.
You could use an INSERT trigger and send them an email on the spot as soon as they join.
See: sp_send_dbmail at http://msdn.microsoft.com/en-us/library/ms190307.aspx
Trigger example: http://www.codeproject.com/KB/database/TriggersSqlServer.aspx
I'm trying to find out if a specific MySQL User is still in use in our system (and what queries it is executing).
So I thought of writing a trigger that would kick in anytime user X executes a query, and it would log the query in a log table.
How can I do that?
I know how to write a query for a specific table, but not for a specific user (any table).
Thanks
You could branch your trigger function on USER().
The easiest would be to have the trigger always fire, but only logs if the user is X.
I would look at these options:
A) Write an audit plugin, which filters events based on the user name.
For simplicity, the user name can be hard coded in the plugin itself,
or for elegance, it can be configured by a plugin variable, in case this problem happens again.
See
http://dev.mysql.com/doc/refman/5.5/en/writing-audit-plugins.html
B) Investigate the --init-connect server option.
For example, call a stored procedure, check the value of user() / current_user(),
and write a trace to a log (insert into a table) if a connection from the user was seen.
See
http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_init_connect
This is probably the closest thing to a connect trigger.
C) Use the performance schema instrumentation.
This assumes 5.6.
Use table performance_schema.setup_instrument to only enable the statement instrumentation.
Use table performance_schema.setup_actors to only instrument sessions for this user.
Then, after the system has been running for a while, look at activity for this user in the following tables:
table performance_schema.users will tell if there was some activity at all
table performance_schema.events_statements_history_long will show the last queries executed
table performance_schema.events_statements_summary_by_user will show aggregate statistics about each statement types (SELECT, INSERT, ...) executed by this user.
Assuming you have a user defined as 'old_app'#'%', a likely follow up question will be to find out where (which host(s)) this old application is still connecting from.
performance_schema.accounts will just show that: if traffic for this user is seen, it will show each username # hostname source of traffic.
There are statistics aggregated by account also, look for '%_by_account%' tables.
See
http://dev.mysql.com/doc/refman/5.6/en/performance-schema.html
There are also other ways you could approach this problem, for example using MySQL proxy
In the proxy you could do interesting things - from logging to transforming queries, pattern matching (check this link also for details on how to test/develop the scripts)
-- set the username
local log_user = 'username'
function read_query( packet )
if proxy.connection.client.username == log_user and string.byte(packet) == proxy.COM_QUERY then
local log_file = '/var/log/mysql-proxy/mysql-' .. log_user .. '.log'
local fh = io.open(log_file, "a+")
local query = string.sub(packet, 2)
fh:write( string.format("%s %6d -- %s \n",
os.date('%Y-%m-%d %H:%M:%S'),
proxy.connection.server["thread_id"],
query))
fh:flush()
end
end
The above has been tested and it does what it is supposed to (although this is a simple variant, does not log success or failure and only logs proxy.COM_QUERY, see the list of all constants to see what is skipped and adjust for your needs)
Yeah, fire away, but use whatever system you have to see what user it is (cookies, session) to log only if the specific user (userID, class) matches your credentials.