SSRS subscription only when data in report - sql-server

I have setup a report that uses a stored procedure to create the dataset. I am sending this report to 4 users using an email subscription on a daily basis. More often than not, the report will not have any data. How do I get the subscription to only send the email when the report has data?

Anyone else who stumbles across this, you can try this little trick. It will throw an error, which will prevent the report from being sent.
IF ##ROWCOUNT = 0 RAISERROR('No Results', 16, 1);

Use a data-driven report, if you're on Enterprise edition. If not, you'll need to see if any rows were returned from the SP first, and only execute the subscription if there are. This is pseudo-SQL, in the absence of a lot of context, however, something like:
IF EXISTS(SELECT 1 FROM YouTable JOIN YourOtherTable WHERE ...) BEGIN
EXEC ReportServer.dbo.AddEvent #EventType='TimedSubscription', #EventData='a6c151ca-ff47-46c0-b807-ad1ac8116769';
END

Related

SQL Server 2008 R2 standard data-drive subs workaround

So after some research I figured out that Standard edition does have the ability to manage data-driven subscriptions, so you'd have to write a custom script or stored procedure to work around it and get the same result.
My goal is be able to edit our existing reports (most of them are done with SSRS but we have a number of them created as SQL Server Agent jobs) so that they only e-mail the report if data is available; if no rows come up I want it to cancel sending the e-mail.
Before tackling an existing report, I tried creating a simple test script to get a better understanding DB Mail and stored procedures, so I came up with this script:
IF Exists ( Select cht_number, cht_itemcode, cht_description from chargetype where last_updatedate>'11/11/2014')
execute msdb.dbo.sp_send_dbmail
#profile_name=Null,
#recipients='email#company.com',
#subject='Test',
#Execute_Query_Database='DB_Name',
#query='Select cht_number, cht_itemcode, cht_description from chargetype where last_updatedate>''11/11/2014''',
#attach_query_result_as_file=1,
#query_attachment_Filename='TEST.csv',
#query_result_no_padding=1,
#query_result_header = 1,
#query_result_width = 256,
#query_result_separator=' '
IF ##ROWCOUNT = 0 raiserror ('No Data', 16, 1)
To test this script, I would edit something in that table so that only the most recent items would be sent in the report. If no data was available, it would just raise the error "No Data".
Can anyone suggest another way of getting this result, or how I could shorten this and be able to use it sort of like a template I could fiddle with to fit in an existing script?

Tracking User activity log for SQL Server database

I have a database with multiple tables and I want to log the users activity via my MVC 3 web application.
User X updated category HELLO. Name changed from 'HELLO' to 'Hi There' on 24/04/2011
User Y deleted vehicle Test on 24/04/2011.
User Z updated vehicle Bla. Name changed from 'Blu' to 'Bla' on 24/04/2011.
User Z updated vehicle Bla. Wheels changed from 'WheelsX' to 'WheelsY' on 24/04/2011.
User Z updated vehicle Bla. BuildProgress changed from '20' to '50' on 24/04/2011
My initial idea is to have on all of my actions that have database crud, to add a couple lines of code that would enter those strings in a table.
Is there a better way of checking which table and column has been modified than to check every column one by one with if statements (first I select the current values, then check each of them with the value of the textbox) I did that for another ASPX web app and it was painful.
Now that I'm using MVC and ADO.NET Entity Data Model I'm wondering if a faster way to find the columns that were changed and build a log like the one above.
You can also accomplish this by putting your database into full recovery mode and then reading the transaction log.
When database is in a full recovery mode then sql server logs all Update, insert and delete (and others such as create, alter, drop..) statements into it's transaction log.
So, using this approach you dont need to make any additinal changes to your application or your database structure.
But you will need 3rd party sql transaction log reader. Red gate has a free solution for sql server 2000 only. If your server is 2005 or higher you would probably want to go with ApexSQL Log
Also, this approach will not be able to audit select statements but it's definately the easiest to implement if you dont really need to audit select queries.
The way I see, you have two options:
Create triggers in the database side, mapping changes in a table by table basis and getting result into a Log table
OR
Having the code handle the changes. You would have a base class with data and with reflection you could iterate all object properties and see what has changed. And then save that into your Log table. Of course, that coding would be on your Data Access Layer.
By the way, if you have a good code structure/architecture, I would go with the second option.
You could have a trigger (AFTER insert/update/deelte) on each table you want to monitor. The beauty is columns_updated() which returns a barbinary value, indicating which columns have been updated.
Here is some snippet of code that I put in each trigger:
IF (##ROWCOUNT = 0) return
declare #AuditType_ID int ,
#AuditDate datetime ,
#AuditUserName varchar(128),
#AuditBitMask varbinary(10)
select #AuditDate = getdate() ,
#AuditUserNAme = system_user,
#AuditBitMask = columns_updated()
-- Determine modification type
IF (exists (select 1 from inserted) and exists (select 1 from deleted))
select #AuditType_ID = 2 -- UPDATE
ELSE IF (exists (select * from inserted))
select #AuditType_ID = 1 -- INSERT
ELSE
select #AuditType_ID = 3 -- DELETE
(record this data to your table of choice)
I have a special function that can decode the bitmask values, but for some reason it is not pasting well here. Message me and I'll email it to you.

information_schema.columns returns 0 rows to my SQL Server Agent

I'm just stuck in with this problem and unfortunately I couldn't find anything to it not even when googling around...
I'm running the following query on a SQL Server 2005 database:
select #TableCount = count(distinct table_name)
from information_schema.columns
And I'm getting different results for #TableCount in different databases, such as:
59,
22,
..etc
BUT when I let my SQL Server Agent run the same query on the same databases he always gets 0 (zero) as the result. I.e. no exception, no error message that something's wrong with his access rights - just simply a 0 (zero) as the result.
Plz help if you have any idea:
What could be wrong with my SQL Server Agent?
How comes that I don't get any error message whatever the problem is?
Thx a lot in advance for any ideas / suggestions !!!
I am sure a decade later is not helpful for #Gustin, but someone else might come across this. The issue is likely permissions on the user tables.
Ref: Microsoft documentation on COLUMNS (Transact-SQL) https://learn.microsoft.com/en-us/sql/relational-databases/system-information-schema-views/columns-transact-sql?view=sql-server-ver15
"Returns one row for each column that can be accessed by the current user in the current database."
I validated by creating a new table, confirmed user got 0 rows from
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = <userTableName>
Granted SELECT permission to the user, then rows were returned by the same query.
Which database do you have set as the default?
Model returns 0 for me.

How to send email from execute sql task?

How can i send email if execute sql task get executed and loads a table. so, if table is loaded with any record send email, if not loaded no email.
Appreciate any help.
after that task add another task that checks if there are any rows in the table
something like
IF EXISTS (SELECT 1 FROM Yourtable)
BEGIN
EXEC msdb.dbo.sp_send_dbmail ---------
END
read up on sp_send_dbmail here: http://msdn.microsoft.com/en-us/library/ms190307.aspx
its cool i solved it. i used two execute sql tasks and first one for loading data into the table, second one counting the records and i put variable on green arrow #MyVariable > 0 and connected the send mail task.
Thanks to all.

simple way to know the updates in table

hi just wanted to know is there any way to know if any update happens in column like Ex:Author ID, and once its update happen in column is there any simple way so that all the managers should know that new author update happen in Database or via email, i am a newbie, if anyone help me step by step on this it will be really greatful for me at the appraisel time please help on this..
Thanks
aaru
You need to create a trigger
CREATE TRIGGER reminder2
ON Sales.Customer
AFTER INSERT, UPDATE, DELETE
AS
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'AdventureWorks Administrator',
#recipients = 'danw#Adventure-Works.com',
#body = 'Don''t forget to print a report for the sales force.',
#subject = 'Reminder';
However, using the sp_send_dbmail is not appropriate from within a stored procedure as it will slow down the update of a row. Meaning that everytime an update is done to the row, it will have to wait until the email is sent.
Instead, you should use another table to store the action on the row, have a batch job or a service scan the table and send the email itself.
For example:
CREATE TRIGGER SendEmailOnUpdate
ON Author
AFTER UPDATE
AS
INSERT INTO Notification(AuthorId) VALUES(updated.AuthorId);
The create a Windows Service that scan the table Notification and take one row at a time and send an email against the data it contains.
See MSDN for more information about triggers.
You might want to use a Sql Trigger to create a log of all the updates that occur on certain tables and fields.
You may want to use the UPDATE() function (lookup in books on-line) within the trigger to test just for changes to the field you are interested in (i.e. Author)
Actually, using sp_send_dbmail inside a trigger isn't so bad. Unlike the MAPI xp_sendmail days, sp_send_dbmail just queues up the email (essentially writing a record into a table). It will not cause the trigger to wait for the email to be sent. While SQL BOL says the sp "sends an email message", the result of a successful call is the message "Mail queued."
I am still not sure I would call it from a trigger, but I'd now consider it with dbmail.

Resources