SQL Server : detect column changes - sql

I am trying to detect any changes in a column. Let me describe my problem exactly.
Let's say I have 400 stored procedures and 20 of them changes a column named ModDate in a table Users. But the ModDate column is not enough for me to achieve my goal. I need a dirty bit column let's say IsChanged.
My solution would be find and check the procedures that updates Users.ModDate and change these procedures to update IsChanged as well. But this is not efficient in time. Also, I may miss some procedures and this will cause problems.
So, my question; is it possible to alter a table/column to create an "on change" trigger? When any procedure changes the value of Users.ModDate, SQL Server will update the IsChanged column as 1 automatically.
Thanks for your answers.

You can create a trigger on a column for different crud events.
See https://www.sqlservertutorial.net/sql-server-triggers/sql-server-create-trigger/
`CREATE TRIGGER [schema_name.]trigger_name ON table_name AFTER {[INSERT],[UPDATE],[DELETE]} [NOT FOR REPLICATION] AS {sql_statements`}

Related

Check for changes after update

I want to check if values from a table were changed after the update process and store the sysdate in a column. For updating, I'm using a stored procedure with more than 60 parameters (number of columns from my table). The stored procedure is called every time a user hit the button save in the UI. Does anyone know how can I achieve this?
I mention that I can't use triggers because of the performance policy.
Thank You!

SQL update statement setting the same value back

I am looking at a stored procedure in SQL and have come across a curious update statement. It goes like this.
UPDATE dbo.Table_name
SET [Column_name] = [Column_name]
WHERE [Column_ID] = '2564-5131'
I fail to understand the significance of this update statement.
I new to SQL so might be missing a point here.
EDIT:
I checked the table defination for triggers as mentioned in some comments below but didn't find anything.
The table defination only contains these
Primary key clustered
Foreign key that references another table
Constraint for a column with TinyInt type to check the value remains within bounds
And a non-clustered index on one column
This does nothing by itself, but there is probably a trigger defined on the table for updates that will do something. Check the table definition for triggers.
Ok, so I managed to figure out what that update does and thought would document it here.
It turns out that this exact update statement is present in multiple stored procedures and this non-functional update acts as an explicit lock between these stored procedures. It causes all the stored procs to be serialized.
I guess this is not an optimal design for maximum throughput. Apparently this was done to avoid many deadlocks that were observed if the stored procs were not serialized.

Is there any method in Triggers to skip update/insert from particular user in DB2?

I don't have much knowledge in TRIGGERS, below is my doubt kindly suggest any answers.
SYSTEM:
I have a table called A with Triggers, it designed in such a way if any update/insert happens it will update/insert the same in Table B.
PROCESS:
Table A will get updated by multiple users
MY QUESTION:
I want to block one user/Batch JOB. i.e. if any update/insert is performed by this user/BatchJob in TABLE A, it wont be propagated to Table B.
IS it possible in DB2 Triggers? If so Please Help me. Thanks in Advance!
You could add a new table to your DB that contains users you want to block (or add a column to an existing user table).
Then change your trigger like this
if current_user is not in blocked_user_table
then
insert in table b
end

Should I use the template from MS SQL Management Studio to create new triggers?

If you create a new trigger in MS SQL Management Studio by using the GUI, it gives you this template:
--====================================
-- Create database trigger template
--====================================
USE <database_name, sysname, AdventureWorks>
GO
IF EXISTS(
SELECT *
FROM sys.triggers
WHERE name = N'<trigger_name, sysname, table_alter_drop_safety>'
AND parent_class_desc = N'DATABASE'
)
DROP TRIGGER <trigger_name, sysname, table_alter_drop_safety> ON DATABASE
GO
CREATE TRIGGER <trigger_name, sysname, table_alter_drop_safety> ON DATABASE
FOR <data_definition_statements, , DROP_TABLE, ALTER_TABLE>
AS
IF IS_MEMBER ('db_owner') = 0
BEGIN
PRINT 'You must ask your DBA to drop or alter tables!'
ROLLBACK TRANSACTION
END
GO
Should I use this template?
I dont know anything about triggers, but I think I need to use them. The purpose in this case is that on an insert to the table, I need to update one of the fields.
Please help me get started!
OK to begin with that is the wrong template if you want an ordinary trigger that one is a trigger on making structural changes to the table itself.
If you decide to do a trigger that affects data (as opposed to structure), there are several things you need to know. First and by far the most critical, triggers operate on sets of data not one row at time. You must write any trigger to handle multiple row inserts.updates or deletes. If you end up with any code setting the value in inserted or deleted to a variable, there is a 99% chance it will not work properly if multiple records are involved.
What is inserted or deleted you ask? That is the next thing you need to know about triggers, there are two pseudotables (inserted and deleted) that are only available in a trigger (or an output clause) which contain the new information being inserted or the updated values (in the inserted table) and the old information being deleted or being changed by an update (in the deleted table). So an insert has values in inserted, a delete has values in deleted and an update has values in both. Use these in your trigger to pull the values you need to change.
Since you don't know anything about triggers, I would say no, don't use the template.
Read the books online page for Create Trigger and write the trigger by hand.
There is probably more in that template code than you actually need. Read the manual and keep it simple.
If you don't know anything about triggers then I would strongly suggest that you read up on them before implementing them. Get Triggers right and they can make your life a lot easier; get it wrong and Triggers will cause you a lot of trouble.
I would suggest starting off with this tutorial
http://www.sqlteam.com/article/an-introduction-to-triggers-part-i
You can use the above SQL as a template or you can simply write your own. I would suggest you write your own as you'll understand what you are doing. Obviously only do this after you have done some serious reading on triggers. Check out MSDN too

Force SQL Server column to a specific value

Is it possible to force a column in a SQL Server 2005 table to a certain value regardless of the value used in an insert or update statement is? Basically, there is a bug in an application that I don't have access to that is trying to insert a date of 1/1/0001 into a datetime column. This is producing a SqlDateTime overflow exception. Since this column isn't even used for anything, I'd like to somehow update the constraints on the columns or something in the database to avoid the error. This is obviously just a temporary emergency patch to avoid the problem... Ideas welcome...
How is the value being inserted? If it's through a stored proc... you could just modify the Sproc to ignore that input parameter.
if it's through client-side generated SQL, or an ORM tool, otoh, then afaik, the only option is a "Before" Trigger that "replaces" the value with an acceptable one...
If you're using SQL 2005 you can create an INSTEAD OF trigger.
The code in this trigger wil run in stead of the original insert/update
-Edoode
I'd create a trigger to check and change the value
If it is a third party application then I will assume you don't have access to the Stored Procedure, or logic used to generate and insert that value (it is still worth checking the SPs for the application's database though, to see if you can modify them).
As Charles suggested, if you don't have access to the source, then you need to have a trigger on the insert.
The Microsoft article here will give you some in depth information on creating triggers.
However, SQL Server doesn't have a true 'before insert' trigger (to my knowledge), so you need to try INSTEAD OF. Have a look here for more information. In that article, pay particular note of section 37.7, and the following example (again from that article):
CREATE TRIGGER T_InsertInventory ON CurrentInventory
INSTEAD OF INSERT AS
BEGIN
INSERT INTO Inventory (PartNumber, Description, QtyOnOrder, QtyInStock)
SELECT PartNumber, Description, QtyOnOrder, QtyInStock
FROM inserted
END
Nick.
the simplest hack would be to make it a varchar, and let it insert that as a string into the column.
The more complicated answer is, you can massage the data with a trigger, but it would still have to be valid in the first place. For instance I can reset a fields value in an update/insert trigger, but it would still have to get through the insert first.