Informix trigger for deleting one record - sql

When I perform an task, two rows gets inserted in my table ie. duplication. I need to remove the duplicate by using an after insert trigger. I need to delete one duplicate record from those 2. I need something like this
CREATE TRIGGER del_rec
INSERT ON table1
AFTER(EXECUTE PROCEDURE del_proc());
CREATE PROCEDURE del_proc()
//check field a,b,c of this table already exists for this id. if yes delete the second one
END PROCEDURE;
For example:
table 1:
a b c d e
1 1 1 2 2
1 1 1 2 2
it should delete the second row.

Your table is misdesigned if duplicates can be inserted into it. You should have a unique constraint ensuring that it does not happen.
Assuming that you can't fix the table for some reason, then:
CREATE TRIGGER ins_table1
INSERT ON table1 REFERENCING NEW AS new
FOR EACH ROW (EXECUTE PROCEDURE ins_table1(new.a, new.b, new.c));
This assumes that columns a, b and c are sufficient to uniquely identify the row. I've renamed the trigger and procedure to more accurately reflect what/when they are relevant; del is not all that appropriate as a prefix for something called on INSERT.
CREATE PROCEDURE ins_table1(new_a INTEGER, new_b INTEGER, new_c INTEGER)
DEFINE l_a LIKE table1.a;
FOREACH SELECT a INTO l_a
FROM table1
WHERE a = new_a AND b = new_b AND c = new_c
RAISE EXCEPTION -271, -100;
END FOREACH;
END PROCEDURE;
This is called for each row that's inserted. If the SELECT statement returns a row, it will enter the body of the FOREACH loop, so the exception will be raised and the INSERT will be aborted with a more or less appropriate error (-271 Could not insert new row into the table; -100 ISAM error: duplicate value for a record with unique key).
If you try to do this validation with an AFTER trigger, you have to scan the entire table to see whether there are any duplicates, rather than just targeting the single key combination that was inserted. Note that in general, an INSERT can have multiple rows (think INSERT INTO Table SELECT * FROM SomeWhereElse). The performance difference will be dramatic! (Your query for an AFTER trigger would have to be something like SELECT a, b, c FROM table1 GROUP BY a, b, c HAVING COUNT(*) > 1.)

Why not just use SELECT UNIQUE to avoid inserting duplicate values, or to remove duplicate values which already exist in the table?

Related

Use cursor value to make combination dynamically and use it while inserting in a row

I am pulling values in a cursor say from table called my_table and depending on the condition it may return a, b, c, d etc. Now with those values I need to prepare a combination of a, ab, ac, ad, b, bc,bd, c, cd and so on. I want to use these values while inserting a row in another 2 tables where in one table I will use the combination values together in a column and in another table I'll use original values separately used in the combination. The first table id will be the FK of the second table while inserting data. How to achieve the same.
You can do something like as mentioned below, change the code as per your requirement.
CREATE OR REPLACE TRIGGER my_table_trg
AFTER INSERT
ON my_table
FOR EACH ROW
DECLARE
CURSOR comb_values
IS
SELECT .......;
BEGIN
FOR i IN comb_values
LOOP
INSERT INTO table1
VALUES (i.combination_values);
INSERT INTO table2
VALUES (i.non_combination_values);
END LOOP;
END;

How to create a sequence in oracle from top to bottom

So I have two tables in Oracle. Table A is the master table and Table B is data retrieved from a contractor. They both have the same general structure. In the end, I would like to INSERT INTO TABLE A(SELECT * FROM TABLE B). However the primary key column in Table B does not exist. How do you suggest creating a primary key that at the same time generates a sequence from 4328 and on for every row in Table B?
I proceeded to do the following:
create sequence myseq
increment by 1
start with 4328
MAXVALUE 99999
NOCACHE
NOCYCLE;
Then created a PK column to finally implemented the following:
INSERT INTO TABLE B (PK) VALUES(MYSEQ.nextVal);
But no results yielded except putting in one row at the very end. I want every row to be populated starting at 4328 and ending 291 rows later.
Sorry, but I don't know if I undestand your problem.
Do you want to insert one row in Table A and Table B with equal PK value?
You can do it by procedure put the sequence value in a variable before insert the rows, for example:
BEGIN
SELECT MYSEQ.nextval INTO v_SEQUENCE FROM dual;
insert into table_A values (v_SEQUENCE,1,2,3);
insert into table_B values (v_SEQUENCE,1,2,3);
END;
If you can get all rows from Table_B and insert into table_A with a PK you can do for example:
INSERT INTO TABLE_A (SELECT MYSEQ.nextval, B.* FROM TABLE_B B)
Is it?
Your approach only calls the sequence once. What you want to do is perform a loop in PL/SQL to call the sequence as many times as needed:
BEGIN
FOR x IN 1 .. 291 LOOP
INSERT INTO TABLE B (PK) VALUES(MYSEQ.nextVal);
END LOOP;
END;
Make sure you drop and recreate your sequence to ensure it starts at the right value.

Trigger - After insert and delete example

I have a requirement as a trigger should get fired when any row is inserted or deleted from table FAB which contains num as unique value. and depending upon that num value, another table should be update.
e.g.
FAB table
num code trs
10 A2393 80
20 B3445 780
Reel table
reelnr num use flag
340345 10 500 1
when num 10 from FAB table gets deleted(or any new num gets inserted), the trigger should get fired and should check the reel table which contains that num value and give the reelnr.
How to proceed with this?
you can Use Inserted & Deleted Table in SQL
These two tables are special kind of table that are only available inside the scope of the triggers.
If you tries to use these tables outside the scope of Triggers then you will get Error.
Inserted : These table is use to get track of any new records that are insert in the table.
Suppose there are Six rows are inserted in your table then these table will consist of all the six rows that are inserted.
Deleted : These table is used to track all the Deleted record from your tables.
Last delete rows will be tracked by these table.
For Insert :
CREATE TRIGGER TR_AUDIT_Insert
ON Reel_table
FOR INSERT
AS
BEGIN
INSERT INTO Reel_table (reelnr, num, use, flag)
SELECT
reelnr,
num,
use,
flag
FROM
INSERTED
END
For Delete :
CREATE TRIGGER TR_AUDIT_Delete
ON Product
FOR DELETED
AS
BEGIN
INSERT INTO Reel_table (reelnr, num, use, flag)
SELECT
reelnr,
num,
use,
flag
FROM
DELETED
END
Note :
I don't know from where these three reelnr, use flag values you are getting
So, Please modify this as per your need.
This is the format of the Triggers that normally we use.
You also can do this by using single trigger also
I dont know what is your exact requirement
If you want to achieve by only single Trigger then you can refer this link :
Refer

When value of a column changes in one table , a record should be inserted in other table in oracle DB

I want a SQL procedure / function to solve the below mentioned problem:
I have 2 tables - Table A and table B.
Table A has 3 columns - name, number and flag.
Table B has 2 columns - name and number.
When a value of flag column changes in table A, a record should be inserted in table B with the same values of name and number from table A.
How can I achieve this?
You can achieve this by using triggers.
Triggers are procedures that are stored in the database and are implicitly run, or fired, when something happens.
You can write triggers that fire whenever and INSERT, UPDATE, or DELETE operation is performed on a particular table or view.
General Syntax:
CREATE TRIGGER WRITE_TRIGGER_NAME_HERE
BEFORE UPDATE ON TABLE_A
FOR EACH ROW
BEGIN
WRITE_INSERT_STATEMENT_HERE_FOR_TABLE_B
END;

Copy data to another table before update or insert. Use stored procedure?

I have two tables that I need to update in a database. I am updating these tables from data in another database. If a record in table 1 gets updated, I need the old information in table 1 to be stored in table 2. I need logic in place to make a comparison and then update Table 2 if needed. My question is, what is the best way to do this? I am thinking a stored procedure would be the way to go, but I'm not sure.
Here is a more visual explanation.
Table 1
Student Grade
james 6
sarah 5
Table 2
EMPTY
Lets say that the data below is what I am pulling from another database.
Other Database
Student Grade
james 6
sarah 4
tom 7
Here is some sloppy logic that may help explain what I need to do.
--If records match do nothing
IF otherDatabase.student = table1.student AND otherDatabase.grade = table1.grade THEN do nothing
--If partial match copy old data to table 2 and insert new data to table1
IF otherDatabase.student = table1.student AND otherDatabse.grade != table1.grade
THEN copy table1.student to table2.student AND copy table1.grade to table2.grade THEN UPDATE table1.grade from otherDatabase.grade
--If no match copy new data to Table1
IF otherDatabase.student != table1.student AND otherDatabase.grade != table1.grade THEN INSERT otherDatabase.student AND otherDatabase.grade INTO table1
In my example, James would not get touched, sarah would get moved to table 2 and then inserted into table 1 with new grade and tom would get inserted into table 1.
I am very sorry if this doesn't make sense. Please allow me to clarify if needed. Thanks
You could do it with a stored procedure, but I would use a trigger.
With a stored procedure, I'd perceive you using a cursor on the otherDatabase table to read through the records and compare each with the values in Table1 to determine whether Table1's data needed to be written to Table2, and if so, to do it.
With a trigger, I would simply update the data in Table1 by whatever means, without concerning myself with what the overwriting data is, and in the trigger,
use the old and new values using the ##Inserted & ##Deleted (system) tables to determine if the old values (##Deleted) needed to be written to Table2. Eg
INSERT Table2 (Student, Grade)
SELECT d.Student, d.Grade
FROM ##Deleted d LEFT JOIN ##Inserted i ON d.[Key] = i.[Key]
WHERE (d.Student <> i.Student OR d.Grade <> i.Grade) AND d.[Key] IS NOT NULL
Drop procedure if exists getCID;
delimiter //
CREATE PROCEDURE getCID(IN cid varchar(100))
BEGIN
create table Temp as(select i.invoice_no,i.cust_id,b.tot_amount,b.paid_amount,b.bal_amount from invoice_item_info i,bill_info b where i.invoice_no=b.invoice_no and i.cust_id=cid);
select * from Temp;
select DISTINCT cust_id,count(invoice_no),sum(tot_amount),sum(paid_amount),sum(bal_amount) from Temp;
Drop table Temp;
END
//
delimiter ;