In tableA I have an ID field that I want to be a value from tableB when inserting into tableA. It should however cycle through all values in tableB for each record entered. So if I have id's in tableB of 0, 1, 2, 3 then on first insert to tableA it would assign tableB value 0, on 2nd insert it should use tableB 1, then 2, then 3, then back to 0, and just loop in a cycle like this.
I'm guessing I'd need a table to track which one should be the next value and then in my trigger use that value then get the next value to use for the next insert trigger. Would there be any other ways that someone can think about doing this outside of a stored proc?
From what I have understand is you trying to load the data from TableB into TableA looping through IDs from TableB.
If the data in TableB is historical data that you want to load it on to TableA, then you need stored procedure with cursor inside so that you can do initial delta load from B to A. you dont need another table here in that case since you are using Cursor in Stored Procedure.
If you want TableA to be populated when there is an insert or update on TableB then you can use trigger on TableB.
Related
I created three tables A (id, name, date, realnumber, integer), B (id, name, date, realnumber, integer), and C which is identical to table A. It only has two more columns called integerB and sequence s. I want to create a trigger which would fire after insert on table B for each row input so that it saves the referenced row of Table A and adds integer from input row of table B in column integerB of table C. If the row already exists in Table C only integerB should be added. When it comes to sequence s, next value is added with first insert of row of table A.
Simple explanation: Table C is a copy of table A with two additional columns: integerB and sequence. The point of the trigger is to add new rows from table A without repetition, integerB from table B(integer in table B) and sequence should start with 1 and increment by 1. If the row in table A is repeated then only integerB should be updated.
I did not work with triggers that much, so I am not sure how to solve the problem when I have to insert data from multiple tables. Here is my trigger.
CREATE OR REPLACE TRIGGER trig1
AFTER INSERT ON B
FOR EACH ROW
INSERT INTO C (integerB) VALUES (NEW.integer);
INSERT INTO C (id, name, date, realnumber)
SELECT a.id, a.name, a.date, a.realnumber FROM A a;
END;
/
First off you really need to use better column and table names as a lot of these are reserved words... This makes everything far more complicated than it needs to be.
It isn't entirely clear what you want to do but it seems that if someone was to insert a record with ID = 1 into B then you want to get the values from A for ID = 1 and store them in C along with the integer value inserted into B
In which case you want to use an MERGE statement (UPSERT) in your trigger and something like
CREATE OR REPLACE TRIGGER T1
AFTER INSERT ON B
FOR EACH ROW
BEGIN
MERGE INTO C C
USING (SELECT * FROM A WHERE ID = :NEW.ID) A
ON (C.ID = :NEW.ID)
WHEN MATCHED THEN UPDATE
SET C.INTEGERB = :NEW.INTEGER,
C.SEQUENCE = C.SEQUENCE + 1
WHEN NOT MATCHED THEN
INSERT (ID, NAME, DATE, REALNUMBER, INTEGER, INTEGERB, SEQUENCE)
VALUES (A.ID, A.NAME. A.DATE, A.REALNUMBER, A.INTEGER, :NEW.INTEGER, 0);
END;
/
For sequence this has been set to 0 when a new record is inserted into C and then incremented each time integerB is updated. I am not sure if this is waht you want or not.
You should be able to tweak this to match the exact joins and logic you need.
Tip
Get your SQL statement working with literal values first and then translate it into your trigger. It will be much easier if you can get something working manually first before you attempt to make things more complicated
I need to insert data of one table to another table. All the values are from the table except one SO_ID. It is coming from the Item on the page. How do I do it?
insert into T_SORDER_ITEM_INWARD
(
select sd.ID, SO_ID
into :P25_SO_ID, sd.STOCK_ID,sd.ITEM_ID,sd.UOM_ID,
sd.ITEM_CONDITION_ID,sd.ORIGINAL,sd.ACTUAL,sd.WIDTH,sd.LENGTH,sd.STOCKQTY,
sd.KANTA,sd.RATE,sd.PACKET, sd.LABEL_METER, sd.EXCESS_SHORT,sd.LOCATION_ID,
sd.CLIENT_INITIAL, sd.FIN_YEAR, sd.SERIAL_NO
from T_STOCK_DETAIL sd join t_stock_master sm
on sd.stock_id = sm.stock_id
where sm.customer_id = p25_customer
)
A simplified example:
insert into another_table (id, name, location)
select :P25_SO_ID,
t.name,
t.location
from this_table t
Always name all columns you're inserting into (first line in my example).
Your query is impossible to understand. Not just because syntax is wrong, but because we have no idea which column is supposed to get which value.
How do I add data in a table which contains attributes of two different tables which are not linked together?
Table 1 has col1,col2,col3 (assume all are numbers)
Table 2 has col4,col5,col6 (assume all are numbers)
Table 3 has A,B,C,D,E,F (assume all are numbers)
Question is that if any insertion occurs on table 1 and table 2, their data should be loaded in table 3.
I used the normal approach
of
create or replace trigger trig_name
before insert on table1,table2 --> not allowed
for each row
begin
if inserting then
insert into table3 values (:new.col1,:new.col2,:new.col3,:new.col4,:new.col5,:new.col6)
end if;
end;
/
So if I have to make two different triggers for table 1 and table 2, wouldn't that create two rows of data leaving some columns null?
Although creating a view as suggested by #EdStevens is (IMO) a superior answer, what you want can be done. And yes it requires 2 triggers. In Oracle, and all other DBMS that I'm aware of, a trigger can only fire on 1 table.
However, they can be reduced somewhat. There is no need for the "if inserting" test. The trigger is declared as "on insert" therefore the test will always be true. The actual issue it you cannot refer columns from table2 in the table1 trigger and likewise the other way around. What you need is to name the columns you are inserting, actually always a better approach. So:
create or replace trigger table1_bir
before insert on table1
for each row
begin
insert into table3(col1, col2, col3)
values (:new.col1,:new.col2,:new.col3);
end;
/
create or replace trigger table2_bir
before insert on table2
for each row
begin
insert into table3(col4, col5, col6)
values (:new.col4,:new.col5,:new.col6);
end;
/
I have two table,and they are connected by one field : B_ID of table A & id of table B.
I want to use sql to insert data to this two table.
how to write the insert sql ?
1,id in table B is auto-increment.
2,in a stupid way,I can insert data to table B first,and then select the id from table B,then add the id to table A as message_id.
You cannot insert data to multiple tables in one SQL statement. Just insert data first to B table and then table A. You could use RETURNING statement to get ID value and get rid of additional select statement between inserts.
See: https://oracle-base.com/articles/misc/dml-returning-into-clause
Have you heard about AFTER INSERT trigger? I think it is what you are looking for.
Something like this might do what you want:
CREATE OR REPLACE TRIGGER TableB_after_insert
AFTER INSERT
ON TableB
FOR EACH ROW
DECLARE
v_id int;
BEGIN
/*
* 1. Select your id from TableB
* 2. Insert data to TableA
*/
END;
/
Let say I have table my table has values(which they are varchar):
values
a
o
g
t
And I have insert a new value called V
values
V
a
o
g
t
Is there a way or query that can specify what is the last value was insert in the column ? the desired query : select * from dual where rown_num = count(*) -- just an example and the result will be V
Rows in a table have no inherent order. rownum is a pseudocolumn that's part of the select so it isn't useful here. There is no way to tell where in the storage a new row will physically be placed, so you can't rely on rowid, for example.
The only way to do this reliably is to have a timestamp column (maybe set by a trigger so you don't have to worry about it). That would let you order the rows by timestamp and find the row with the highest (most recent) timestamp.
You are still restricted by the precision of the timestamp, as I discovered creating a SQL Fiddle demo; without forcing a small gap between the inserts the timestamps were all the same, but then it only seems to support `timestamp(3). That probably won't be a significant issue in the real world, unless you're doing bulk inserts, but then the last row inserted is still a bit of an arbitrary concept.
As quite correctly pointed out in comments, if the actual time doesn't need to be know, a numeric field populated by a sequence would be more reliable and performant; another SQL Fiddle demo here, and this is the gist:
create table t42(data varchar2(10), id number);
create sequence seq_t42;
create trigger bi_t42
before insert on t42
for each row
begin
:new.id := seq_t42.nextval;
end;
/
insert into t42(data) values ('a');
insert into t42(data) values ('o');
insert into t42(data) values ('g');
insert into t42(data) values ('t');
insert into t42(data) values ('V');
select data from (
select data, row_number() over (order by id desc) as rn
from t42
)
where rn = 1;