I'd like to convert a stored proc into a trigger. The stored proc is supposed to be run after inserts/updates, but users forget to execute it more often than not!
The stored proc inserts recalculated values for some rows:
--Delete rows where RowCode=111
DELETE FROM dbo.TableA WHERE [year]>=1998 AND RowCode=111
--Insert new values for RowCode=111 for years>=1998
INSERT INTO dbo.TableA
SELECT [Year], RowCode=111, ColCode, SUM(Amt) AS Amt
FROM dbo.TableA
WHERE [Year]>=1998 AND RowCode IN (1,12,23) AND ColCode=14
GROUP BY [Year], ColCode
I'd like to put this into a trigger so that the users don't have to think about running a procedure.
I have the following started, but I'm not sure if i'm on the right track. Should I be using FOR, AFTER or INSTEAD OF?
CREATE TRIGGER TRIU_TableA
ON TableA
FOR INSERT,UPDATE AS
BEGIN
SET NOCOUNT ON
IF EXISTS (SELECT * FROM Inserted WHERE RowCode=111)
BEGIN
INSERT INTO TableA
SELECT [Year], RowCode, ColCode, SUM(Amt) AS Amt
FROM Inserted
WHERE [Year]>=1998 AND RowCode IN (1,12,23) AND ColCode=14
GROUP BY [Year], ColCode
END
END
Any help on how to go about this would be very much appreciated.
Many thanks
Mark
You forgot the delete part.
But why doesn't your application just run the existing proc automatically after every insert/update? Are people updating your database from a query window?
Make it an AFter trigger, After and For are the same, but after is the newer syntax.
You should be using FOR
Comparing the Trigger to the Stored Proc it all looks fine.
What other problems do you have?
Related
I have a set of SQL queries that has some dynamic values in it. Every time I need to manually update those dynamic values and ask the DB team to run those SQL queries. For example, in the below set of SQL queries, values such as 1001, WASTE MANAGEMENT, WASTE MANAGEMENT_SUB, 3846333 are dynamic values that need to be modified for a different set of values. I am looking for a way to write some stored procedures so that these values can be added dynamically and execute that procedure to insert into DB. I am basically a UI developer and new to automating SQL queries. Please correct me if my understanding is wrong. Any help or tips on any alternate solutions are appreciated. Any help on how to achieve my understanding is also highly appreciated. Thanks in advance.
INSERT INTO TEMP_BILLERS values('1001','WASTE MANAGEMENT','WASTE MANAGEMENT','WASTE MANAGEMENT_SUB','3846333');
INSERT INTO TBL_FP_BILLER_HEADER(BILLER_NAME)
SELECT UNIQUE(biller_name)
FROM temp_billers
WHERE cif IN ('3846333')
ORDER BY biller_name asc;
INSERT INTO TBL_FP_BILLER_DETAIL(biller_id, cif, service_id, service_name, account_number)
SELECT tblh.biller_id, tbltemp.cif, tbltemp.acc_num, tbltemp.service_name, tbltemp.acc_num
FROM TBL_FP_BILLER_HEADER tblh
INNER JOIN TEMP_BILLERS tbltemp
on tblh.biller_name=tbltemp.biller_name
where tbltemp.cif='3846333';
UPDATE TBL_FP_BILLER_DETAIL
SET PAYMENT_TYPE='A'
,REF_RETENTION_POLICY='90'
, REF_EXPIRATION_POLICY='7'
WHERE CIF='';
Insert into TBL_FP_USER_DEFAULT_BILLER (BILLER_ID,BILLER_NAME,CREATED_DATE,CREATED_BY,MODIFIED_DATE,MODIFIED_BY)
select c.biller_id,'WASTE MANAGEMENT',null,null,null,null
from TBL_FP_BILLER_DETAIL c
where cif='3846333';
COMMIT;
it should be something like:
create procedure example (#ttt nvarchar(100), #ddd nvarchar(100) as
BEGIN
insert into sometable
select something
where somecolumn = #ttt
END
You should create procedure that get required parameters, and then use them in your queries.
I am trying to create SQL trigger which adds a new record to the same table where an insertion is made through a web page. I am not exactly sure how to implement it but I tried the following query
CREATE trigger [dbo].[trgI_DealsDoneInserRecord]
on [dbo].[Terms]
after insert
As
Insert into DealsDone
(Company,Grade,Term,Pipeline,[Index],Volume,Price,[Type],CounterParty,
TermID,GradeID,CPID,Locked,Product)
VALUES
(SELECT Company,Grade,Term,Pipeline,[Index],Volume,Price,[Type],CounterParty,
TermID,GradeID,CPID,Locked,Product FROM inserted)
END
The above query threw an error in the SELECT statement in VALUES.
May I know a way to implement this?
Try this:
CREATE trigger [dbo].[trgI_DealsDoneInserRecord]
ON [dbo].[Terms]
AFTER INSERT
As
BEGIN
INSERT INTO DealsDone
(Company,Grade,Term,Pipeline,[Index],Volume,Price,[Type],CounterParty,
TermID,GradeID,CPID,Locked,Product)
SELECT Company,Grade,Term,Pipeline,[Index],Volume,Price,[Type],CounterParty,
TermID,GradeID,CPID,Locked,Product FROM inserted
END
While I generally advocate against using SELECT *, in this case it seems like a benefit:
By not specifying the fields you can automatically account for changes in the tables without having to update this trigger if you add or remove or even rename fields.
This will help you catch errors in schema updates if one of the tables is updated but the other one isn't and the structure is then different. If that happens, the INSERT operation will fail and you don't have to worry about cleaning up bad data.
So use this:
CREATE TRIGGER [dbo].[trgI_DealsDoneInserRecord]
ON [dbo].[Terms]
AFTER INSERT
AS
SET NOCOUNT ON;
INSERT INTO [DealsDone]
SELECT *
FROM inserted;
There is an syntax issue, and also you are missing BEGIN
The basic syntax is
INSERT INTO table2 (column_name(s))
SELECT column_name(s)
FROM table1;
So try this
CREATE trigger [dbo].[trgI_DealsDoneInserRecord]
on [dbo].[Terms]
after insert
As
BEGIN
Insert into DealsDone
(Company,Grade,Term,Pipeline,[Index],Volume,Price,[Type],CounterParty,
TermID,GradeID,CPID,Locked,Product)
SELECT Company,Grade,Term,Pipeline,[Index],Volume,Price,[Type],CounterParty,
TermID,GradeID,CPID,Locked,Product
FROM inserted
END
Refer:- http://technet.microsoft.com/en-us/library/ms188263(v=sql.105).aspx
I have a problem with the next TRIGGER in SQL server 2008:
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Order int,
#Payment varchar(15)
select #order=OrderID,#payment=PaymentType from inserted
IF #Payment='paypal'
begin
exec PaypalTransactionsUpdate #OrderID=#Order
end
ELSE
begin
Return
end
END
I can't understand why does not work the select from the inserted table. If I use like:
select TOP 1 #order=OrderID,#payment=PaymentType from TABLENAME where PaymentType='Paypal' order by OrderID desc.
It works perfectly, anybody can help me? I want to use the row table inserted to prevent data errors becuase the second statement is no secure, maybe the top one already changes when the trigger runs.
I was using the top1 select this weekend and was working for some orders and for some one don't for no reason. I saw this morning that the row that I want to synchronize , the trigger do it in the next insert, this means, when Paypal order comes stay there without synchronize until the next order comes and rerun the trigger. I am using the after insert modify method and can't understand why this happens. Any ideas?
I will appreciate as well if someone give me a clue how to test Trigger or see the error log of them.
Is there a way to insert records into TABLE B if there is an update in TABLE A?
I don't want to use triggers.
The answer is we can use the OUTPUT clause of instead of triggers:
USE AdventureWorks2012;
GO
IF OBJECT_ID('dbo.vw_ScrapReason','V') IS NOT NULL
DROP VIEW dbo.vw_ScrapReason;
GO
CREATE VIEW dbo.vw_ScrapReason
AS (SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason);
GO
CREATE TRIGGER dbo.io_ScrapReason
ON dbo.vw_ScrapReason
INSTEAD OF INSERT
AS
BEGIN
--ScrapReasonID is not specified in the list of columns to be inserted
--because it is an IDENTITY column.
INSERT INTO Production.ScrapReason (Name, ModifiedDate)
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name,
INSERTED.ModifiedDate
SELECT Name, getdate()
FROM inserted;
END
GO
INSERT vw_ScrapReason (ScrapReasonID, Name, ModifiedDate)
VALUES (99, N'My scrap reason','20030404');
GO
The mechanism for doing this is called triggers.
Saying that you want to do this but don't want to use triggers is like saying you want to see the Eiffel Tower, but you don't want to go to France.
You could, I suppose, write a stored procedure that does all the logic that would have been in the trigger, if you can ensure that all data updates will be via that stored procedure.
If you don't want to use triggers, then you would have three options.
The first would be to wrap all inserts/updates/deletes in stored procedures. Then use only these stored procedures for data modification. This is actually the approach that I generally take.
Another would be to have a process that runs periodically looking for changes to the data. This is actually hard to do for updates. It is pretty easy to do for inserts because you can add an column with a default creation date, so you can readily find what has recently been added.
The third way is to use SQL Server Change Tracking (see here).
You could make a stored procedure that performs both the update in table A and the insert in table B
CREATE PROCEDURE proc_name
#id
#param1
AS
BEGIN
update tableA
set field1 = #param1
where ID = #id
insert into tableB(field1)
values(#param1)
END
I want a SQL trigger to fire when a table is updated. I have a table called SimActivation and a stored procedure called spUpdateMnpDate that takes two parameters, msisdn(varchar) and date(datetime).
When the SimActivation table is updated I want to call the procedure with the new values.
Here is what I got at the moment, after changing it back and forth:
USE StoreSale;
GO
CREATE TRIGGER dbo.tSyncMnpDate
ON [dbo].[SimActivation]
AFTER UPDATE
AS
DECLARE #date datetime
DECLARE #msisdn varchar(10)
SET #date = (select ProcessDate from inserted)
SET #msisdn = (select Msisdn from inserted)
EXEC [spUpdateMnpDate]
#msisdn, #date;
GO
Can anyone point me in the right direction?
Thanks :)
The problem you have is that a trigger will fire when one or more rows have been updated. At the moment you are assuming your trigger will fire for each row, which is not the case in SQL Server.
If the stored procedure you are trying to call is fairly simple I'd pull the code out of there and in to the trigger. But remember you are working with sets of changed rows (even if the change is to only one row) so you have to write your SQL accordingly.
EDIT: I assume your procedure is updating a date where the PK is equal to #msisdn, if so you can do this in your trigger:
UPDATE Your_Table
SET Your_Table.ProcessDate = inserted.ProcessDate
FROM Your_table INNER JOIN inerted ON Your_Table.Msisdn = inserted.Msisdn
Joining the tables ensures it will work for one or many updated rows.