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.
Related
Please help me. I have a table with all my booking status, check in date, check out date. The flow is, when the booking is not paid after 2 days, the status will automatically update to 'NOT PAID'. I'm a newbie in creating trigger. Can anybody please help me. Thanx in advance.
There is no way to do the above with a sql trigger.
You have several options;
Creating a SQL Job as #GuillermoZooby says,
or
You could make the Status column a Computed Column, making the column check the age.
Triggers you are talking about are executed after an INSERT, UPDATE, or DELETE statement on a table or view. So this is not what you are looking for.
You should create Stored Procedure that checks date (I imagine you have a datetime column in the mentioned table) and when the booking is not paid after 2 days, the status field is updated to 'NOT PAID'.
Then you have to create SQL Job (service SQL Agent must be enabled and up) and when you configure schedule to run the previosuly created Stored Procedure just establish the time when you want to run the procedure. For example, once a day.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
SQL Server history table - populate through SP or Trigger?
I am using this trigger
CREATE TRIGGER [dbo].[Band_Level_trg]
-- ALTER TRIGGER [dbo].[Test_PTA_Table_Update_trg]
ON [dbo].[Band_Level]
INSTEAD OF UPDATE
AS
SET NOCOUNT ON
DECLARE #key int
SET #key = (SELECT band_level_id FROM Inserted)
UPDATE Band_Level
SET band_level_name = band_level_name, description = description
WHERE band_level_id = #key
INSERT INTO dbo.Band_Level
(band_level_name, description)
(SELECT band_level_name,description
FROM Inserted)
but i want to show history on another page.it shows history on same page
Given this other question you posted:
maintain history through trigger in asp.net
(which sorry to say, is also horribly explained)
I think I figured out what you want to do. You want to keep a "history" of the changes using this trigger. Also, what I figured is that, you are "showing the history in the same page" because the trigger inserts on the same table you're updating!
The purpose of the history is to do it on ANOTHER table, if not, your history will become actual data of the table you wanna keep a history of.
You should create another table with the same columns and change the trigger accordingly. Just create a Band_Level_History table and change the trigger to save the changes there. That's it. Like this:
Instead of:
INSERT INTO dbo.Band_Level
Put:
INSERT INTO dbo.Band_Level_History
Also, I'd restructure the triggers in a different way. You should REALLY read this article:
https://web.archive.org/web/20210608144836/http://www.4guysfromrolla.com/webtech/091901-1.shtml
It's short so please read it. Also, next time please try to explain things a little better so everyone can understand. I'm aware that you probably have a language barrier but that's OK. Just try and do your best, I'm from Argentina and I can assure you: eventually you'll learn English if you are consistently trying.
Hope this helps
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.
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.
I have a web application (ASP.net 2.0) that has a database (SQL Server) at the background. I'm considering ways how to handle database concurrency if two users insert the same data to the same table at the same time. Are there any way to handle this case? Thanks in advance.
Jimmy
To prevent the same data being INSERTed at the same time, use a unique index on the columns that you want to be unique. The first INSERT will succeed, handle the error for the losing INSERT appropriately.
To prevent 2+ users from modifying the same (existing) record at the same time, use optimistic concurrency http://en.wikipedia.org/wiki/Optimistic_concurrency_control. With SQL Server it's easy to implement optimistic concurrency using a TIMESTAMP column. Read the timestamp with your data. When updating the row, check that the timestamp value is the same. If the timestamps don't match, then the user had (was viewing) an outdated row. Handle that case appropriately.
An example using SqlClient:
command.CommandText = #"
UPDATE tbl
SET LastName = #LastName, FirstName = #FirstName
WHERE ID = #ID AND Timestamp = #Timestamp
";
int rowCount = command.ExecuteNonQuery();
if (rowCount != 1)
throw new DBConcurrencyException();
All you need is:
BEGIN TRANSACTION;
INSERT XXXXXX INTO TABLE1 ......
INSERT YYYYY INTO TABLE2 ........
COMMIT;
if (commit_failed) { tell user to try again!; };
SQLserver will take care of the rest.
If you are trying to prevent duplicates, the simplest answer is to create a UNIQUE index on the column you want to be unique.
If you are trying to prevent more than one user from modifying the same record at the same time, your best bet is to add a last modified timestamp to the table. As you read the record to display on the screen you read the timestamp, and just before you write the changes you check the timestamp again. If it has changed, that means another user has modified the record and you should prevent the change from being written.
Without knowing how your C# code talks to the database (O/R, ADO.NET...), it's difficult to give you a useful answer...
EDIT: all the examples are great, but they won't help if he's using SubSonic for example.