Can I use Stored procedure instead trigger in following case? - sql-server

I've table with columns
studentId,
studentName,
markOne,
markTwo,
total.
I created a trigger to calculate total by adding markOne and markTwo..
whenever I update any one of the mark it automatically updates the total field.
ASK:
But this process can be achieved using Stored Procedure also then why we go for trigger instead Stored Procedure ?

Why would you use either a stored procedure or trigger? The best solution is to use a computed column:
alter table t add total as (markOne + markTwo);
This will calculate the value correctly whenever you refer to total.
Note: You'll need to remove the table from the table or re-create the table without the actual column.

In your condition, you don't require a trigger.You want to only update total field, so don't use triggers.
Trigger use in such a condition, when you add data for markone, marktwo, then it affects many tables.In more than 2-3 table, you need to update the database on two fields.Then you can use triggers.In your case you can simply use stored procedures.
Thanks .

You can create a view for this, so you dont have to alter your table.
create view vwMyTable as
select studentId,
studentName,
markOne,
markTwo,
(markOne + markTwo) as Total
from myTable
Then you can simply do
select * from vwMyTable

Related

SQL Server : fire trigger on SELECT? (Calculated Column)

I need a column to be dynamic as such that a column DaysToExpiration is calculated based on the number of days between now and a date column Expiration Date.
My plan was to add a trigger that fires on a SELECTstatement of the table.
Is this possible? How?
Is there a better way to go about this?
You say "My plan was to add a Trigger that Fires on a SELECT statement of the table."
In that case why have a column at all, why not just select it in your final query?
Select DateDiff(day,getdate(),ExpirationDate) AS [DaysToExpiration]
If it must be persisted and stored in a column then you can make it a computed column as suggested in the comments. Or you could have the table trigger on UPDATE/INSERT so when the ExpirationDate is inserted or updated it sets the DaysToExpiration column to the result of the provided code.
No there is no provision of having trigger on SELECT operation. You can use stored procedure which takes parameters that are fetched from SELECT query and call this procedure after desired SELECT query.

Create column to constantly update with rownum in SQL Server

I have a table in SQL Server database. It has a column testrownum. I want to update the testrownum column to be rownum whenever row is created in the table automatically.
Is there any setting that I can turn on to achieve this?
Perhaps it is best to get a row number at the time you SELECT your data, by using the ROW_NUMBER() function.
As others have pointed out (comments section) the data in a table is essentially unordered. You can however assign a row number for a certain ordering when you select data as follows (suppose a table that only has one column being name):
SELECT
name,
rownr=ROW_NUMBER() OVER(ORDER BY name)
FROM
name_table
You can create trigger function.
Trigger is a function which is called every time data is insert, update or delete from table (you can specify when you want your function to be called when creating trigger). So you can add two triggers, one for insert and one for delete and just increment/decrement value you want.

SQL Server Trigger - Insert the deleted record into another table with deletetime

Currently I have a Item table and a ItemWaste table.
Both tables will have some fields, such as: Name, Amount, etc. But the ItemWaste table will have one more field, which is the TimeWasted.
I wish to automatically insert the DELETED item from the Item table to the ItemWaste table, and at the same time insert the deletion time to the TimeWasted field.
I got no idea how to do this, is it using trigger???
Hope can get some help here... Appreciate any feedback... Thanks....
Sure - not a problem.
You need a basic AFTER DELETE trigger - something like this:
CREATE TRIGGER trg_ItemDelete
ON dbo.Item
AFTER DELETE
AS
INSERT INTO dbo.ItemWaste(Name, Amount, TimeWasted)
SELECT d.Name, d.Amount, GETDATE()
FROM Deleted d
That's all there is! One point to remember: the trigger is called once per batch - e.g. if you delete 100 rows at once, it will be called once and the pseudo table Deleted will contain 100 rows. The trigger is not called once per row (a common misconception).
Yes, simply by writting a trigger you can insert a row when an delete action is performed in another table, have a look at Triggers

SQL Server Trigger. Need Help

I have a table with these columns:
debt
paid
remained
Whenever the paid column is updated I need to recalculate the remained using the following calculation debt minus paid
Could someone help me achieve this?
You could consider a computed column instead.
This article has the syntax for creating from scratch or adding to an existing schema, along the lines of
ALTER TABLE yourtable ADD remainder AS debt - paid
Given table
CREATE TABLE [MyTable]
(
MyTablePK int,
debt numeric(10,2),
paid numeric(10,2),
remainder numeric(10,2)
)
The following trigger will recalculate field Remainder
CREATE TRIGGER tMyTable ON [MyTable] FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
UPDATE mt
Set mt.Remainder = mt.Debt - mt.Paid
FROM [MyTable] mt INNER JOIN Inserted i
on mt.MyTablePK = i.MyTablePK
END
You could also define Remainder as a Computed persisted column, which would have a similar effect without the side effects of triggers
Why perform a calculation in a trigger when SQL can do it for you, and you don't have to worry about triggers being disabled, etc:
CREATE TABLE T (
/* Other columns */
Debt decimal (18,4) not null,
Paid decimal (18,4) not null,
Remained as Debt-Paid
)
This is called a computed column
create trigger DebtPaid
on DebtTable
after insert, update
as if update(paid)
begin
update DebtTable
set remained = inserted.debt - inserted.paid
where customerId = inserted.customerId
end
http://msdn.microsoft.com/en-us/library/ms189799.aspx
http://benreichelt.net/blog/2005/12/13/making-a-trigger-fire-on-column-change/
Computed columns can be good but they are calculated on the fly and arent stored anywhere, for some big queries that perform long calculations having a physical denormalyzed value in Remained controlled by trigger can be better than computed columns.
In your trigger remember to only update rows that were updated , you access those by virtual table Inserted Deleted available in triggers.

SQL Server Trigger that works - fires just once

I want to do some calculations when my table data is changed. However, I am updating my table manually and copy pasting about 3000 rows in once. That makes my trigger work 3000 times, but I want it to do the trigger only once.
Is there a way to do that ?
Thanks.
What's your statement?
If you have multiple inserts then it will fire for each insert you are running. If you want it to execute only once for multiple inserts you must:
Write your insert on a single statement such as insert into foo select * from bar
Your trigger can't be for each row
Other possibility might be:
Disable the trigger
Perform your insertions
Put the trigger code in a stored procedure
Run your stored procedure
If by 'manually' you mean you are copying and pasting into some User Interface tool (like an Access dataGrid) or something like that, then the tool may be issuing one insert statement per row, and in that case you are out of luck the database trigger will be executed once per insert statement. As other answers have mentioned, if you can insert the rows directly into the database, using a single insert statement, then the trigger will only fire once.
The issue is caused because you are manually pasting the 3000 rows. You really have 2 solutions. You can turn off the trigger by doing this:
ALTER TABLE tablename DISABLE TRIGGER ALL
-- do work here
ALTER TABLE tablename ENABLE TRIGGER ALL
and then run the contents of your trigger at then end or you can put your 3000 columns into a temp table and then insert them all at once. This will only setup 1 trigger. If this isn't enough please give us more info on what you are trying to do.
Your trigger will not fire 3000 times if you are modifying 3000 rows in a single statement. Your trigger will fire once and there will be 3000 rows in your virtual 'deleted' table.
If you are limited in how you can import the data into the system that does a single insert per row, I would suggest that you import data into an intermediate table then do the insert into the final table from the intermediate one.
There is a better way.
Re-link the tables that your trigger created or altered, compare them against what's expected to be changed or added and avoid the trigger with a simple WHERE clause.
eg - this trigger I use to INSERT a record, but only once based on a column value existing (#ack).
DECLARE #ack INT
SELECT #ack = (SELECT TOP 1 i.CUSTOM_BOOL_1 AS [agent_acknowledged] FROM inserted AS i)
IF #ack = 1
BEGIN
INSERT INTO TABLEA(
COLA, COLB, etc
)
SELECT
COLA, COLB, etc
from inserted as i
LEFT JOIN TABLEA AS chk --relink to the INSERT table to see if the record already exists
ON chk.COLA = i.COLA
AND chk.COLB = i.COLB
AND etc
WHERE chk.ID IS NULL --and here we say if NOT found, then continue to insert
END

Resources