Triggers in SQL - sql

I am having trouble with the following problem, Just wondering if you could give me any guidance on how i would start this.
Write a trigger to capture an input before it's inserted into a table
so that the value of the insert will be modified to be appended with
the text -previous
Say I have a table called StaffDetails and i could insert info such as ID, How would i apply it to the above problem.
Thank You

Create Trigger trg_name
on StaffDetails
instead of insert
referencing new as new_row
as
begin
#new_row.ID = (#new_row.ID + '_previous')
insert into StaffDetails (.....) values (#new_row.ID, .....)
end
it would probably look something like this, maybe youll have to change some syntax because its not the same for mysql and sql server, for detailed information on syntax for sql server you can look at https://msdn.microsoft.com/en-us/library/ms189799.aspx

Related

How to automate SQL queries to avoid manually executing it everytime

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.

ORACLE TRIGGER INSERT INTO ... (SELECT * ...)

Trigger with Insert into (select * ...)
I'm trying it.
INSERT INTO T_ USERS SELECT * FROM USERS WHERE ID = :new.ID;
not working...
this work.
INSERT INTO T_USERS(ID) VALUES(:new.ID);
Trigger
create or replace trigger "TRI_USER"
AFTER
insert on "USER"
for each row
begin
INSERT INTO T_USER SELECT * FROM USER WHERE ID = :new.ID;
end;​
this work.
INSERT INTO T_USERS(ID) VALUES(:new.ID);
So if it fits to you then try this:
INSERT INTO T_USER(ID) SELECT ID FROM USER WHERE ID = :new.ID;
If you want to select one or more rows from another table, you have to use this syntax:
insert into <table>(<col1>,<col2>,...,<coln>)
select <col1>,<col2>,...,<coln>
from ...;
Perhaps you could post the actual error you are experiencing?
Also, I suggest that you rethink your approach. Triggers that contain DML introduce all sorts of issues. Keep in mind that Oracle Database may need to restart a trigger, and could therefore execute your DML multiple times for a particular row.
Instead, put all your related DML statements together in a PL/SQL procedure and invoke that.
Its not about your trigger but because of INSERT statement
here insert statement works as below
INSERT INTO <TABLE>(COL1,COL2,COL3) VALUES (VAL1,VAL2,VAL3); --> If trying to populate value 1 by one.
INSERT INTO <TABLE>(COL1,COL2,COL3) --> If trying to insert mult vales at a time
SELECT VAL1,VAL2,VAL3 FROM <TABLE2>;
The number of values should match with number of columsn mentioned.
Hope this helps you to understand

SQL trigger to add new records to a table with the same structure when an insertion is made

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

How to update and insert in T-SQL in one query

I have a database that needs from time to time an update.
It may also happens that there are new data while the update runs.
In MySQL there is a option
INSERT INTO IGNORE
I can't find something like this in T-SQL.
No Problem to update ID 1-4 but then there is a new record for ID 5.
The UPDATE query don't work here.
And when I try to INSERT all data again I get a DUPLICATE KEY error.
Additional Infos:
I've forgotten to say that my data come from external sources. I call an API to get data from it. From there I have to insert these data into my database.
I have to admit that I don't understand MERGE. So my solution for now is to use TRUNCATE first and then insert all data again.
Not the best solution but MERGE works, so far I understand it, with two tables. But I have only one table. And to create a table temporarly to use MERGE and later drop that table is in my eyes a bit to much for my little table with 200 records in it.
You can use MERGE keyword. Basically, you need to specify the column(s) on which to join the source of data with target table, and depending on whether it is matching (existing record) or not matching (new record), you run an UPDATE or INSERT.
Reference: http://msdn.microsoft.com/en-us/library/bb510625.aspx
Is a stored procedure an option?
CREATE PROCEDURE dbo.Testing (#ID int, #Field1 varchar(20))
AS
BEGIN
UPDATE tblTesting
SET Field1 = #Field1
WHERE ID = #ID
IF ##ROWCOUNT = 0
INSERT INTO tblTesting (ID, Field1) SELECT #ID, #Field1
END

How to Use FIRE_TRIGGERS in insert sql statement

I am trying to copy data from table "tb_A" to itself (with different primary key).
When "tb_A" table is insert new record, I have written a trigger to populate another table "tb_B" with one record.
I ran the following statement.
INSERT INTO [tb_A]
([NAME])
select top (20)[NAME] from [tb_A]
I was expected 20 new records in "tb_B". But I didn't.
Anyway I saw FIRE_TRIGGERS is using during bulk insert to overcome this issue.
is there is a any way to use it on inset statements too ? Please provide me example.
Gayan
Trigger code (copied from Gayan's comment to gbn's answer):
CREATE TRIGGER UpdatetbB ON [dbo].[tb_A] FOR INSERT
AS
DECLARE #AID as int
SELECT #AID = [ID] FROM inserted
INSERT INTO [tb_B]([IDA]) VALUES (#AID)
The reason your trigger did not work properly is because it is poorly designed. Triggers fire once for each insert even if you are inserting a million records. You havea trigger that makes the assumption it will owrk one record at a time. Anytime you set a value form inserted or deleted to a scalar variable the trigger is wrong and needs to be rewritten. Try something like this instead.
CREATE TRIGGER UpdatetbB ON [dbo].[tb_A] FOR INSERT
AS
INSERT INTO [tb_B]([IDA])
SELECT [ID] FROM inserted
FIRE_TRIGGERS is only for BULK INSERT (and bcp), not "standard" INSERT
I'd expect your trigger to look something like
CREATE TRIGGER TRG_tbA_I ON tb_A FOR INSERT
AS
SET NOCOUNT ON
INSERT tb_B (col1, col2, ...)
SELECT col1, col2, ... FROM INSERTED
GO
You use the special INSERTED table to get the list of new rows in tb_A, then INSERT from this into tb_B. This works for more than one row
If you add the trigger code then we can explain what went wrong.
Edit: your trigger will only read a single row (any row, no particular order) from INSERTED. It isn't set based like my rough example.