I need to create select statement in post_insert trigger. Is it possible if yes then how?
I want to check another table records if it exists then it will update it otherwise insert as new record. Please help.
My block code is that i want to run
DECLARE
EXSIST_TYPE varchar2(50);
EXSIST_NAME varchar2(50);
EXSIST_COMPANY VARCHAR2(100);
BEGIN
SELECT PRO_TYPE, PRO_NAME, COMPANY_NAME INTO EXSIST_TYPE, EXSIST_NAME ,EXSIST_COMPANY FROM STOCK;
IF
:PURCHASE_DETAIL.PRO_TYPE <> EXSIST_TYPE AND
:PURCHASE_DETAIL.PRO_NAME <> EXSIST_NAME AND
:PURCHASE_DETAIL.COMPANY_NAME <> EXSIST_COMPANY THEN*/
IF
:PURCHASE.RADIO_TYPE = 'PURCHASE' THEN
INSERT INTO STOCK(
PRO_TYPE ,
PRO_NAME ,
COMPANY_NAME ,
QUANTITY ,
PURCHASE_RATE,
SALE_RATE ,
RACK_NUM
)
VALUES
(
:PURCHASE_DETAIL.PRO_TYPE,
:PURCHASE_DETAIL.PRO_NAME,
:PURCHASE_DETAIL.COMPANY_NAME,
:PURCHASE_DETAIL.QUANTITY,
:PURCHASE_DETAIL.PRICE,
:PURCHASE_DETAIL.SALE_PRICE,
:PURCHASE_DETAIL.RACK_NUM
);
END IF;
ELSIF
:PURCHASE_DETAIL.PRO_TYPE = EXSIST_TYPE AND
:PURCHASE_DETAIL.PRO_NAME = EXSIST_NAME AND
:PURCHASE_DETAIL.COMPANY_NAME = EXSIST_NAME THEN
IF
:PURCHASE.RADIO_TYPE = 'PURCHASE' THEN
UPDATE STOCK SET
STOCK.QUANTITY = STOCK.QUANTITY+:PURCHASE_DETAIL.QUANTITY
WHERE
STOCK.PRO_TYPE = :PURCHASE_DETAIL.PRO_TYPE AND
STOCK.PRO_NAME = :PURCHASE_DETAIL.PRO_NAME AND
STOCK.COMPANY_NAME= :PURCHASE_DETAIL.COMPANY_NAME;
ELSIF
:PURCHASE.RADIO_TYPE = 'PRCH_RETURN' THEN
UPDATE STOCK SET
STOCK.QUANTITY = STOCK.QUANTITY-:PURCHASE_DETAIL.QUANTITY
WHERE
STOCK.PRO_TYPE = :PURCHASE_DETAIL.PRO_TYPE AND
STOCK.PRO_NAME = :PURCHASE_DETAIL.PRO_NAME AND
STOCK.COMPANY_NAME = :PURCHASE_DETAIL.COMPANY_NAME;
END IF;
END IF;
END;
You never said what happened when you ran that code.
Anyway: requirement you mentioned ("if it exists then it will update it otherwise insert") looks like an excellent candidate for a MERGE statement (also called upsert, as a combination of UPdate and inSERT).
As Forms 6i is an old piece of software, I'm pretty much sure that MERGE can't directly be used there. However, if the underlying database is at least 9i, MERGE will work - create a stored procedure that contains MERGE, and pass form items' values as parameters.
Here's an example (taken from here; have a look for more examples. I'm lazy to create my own code):
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
Related
There is a table which i want to update each row after inserted, when the user_type of my schedule table is a "superuser". I tried to convert the table/column names to "simplify", so some names may not make sense, it's ok.
The trigger code:
CREATE OR REPLACE TRIGGER "TR_UPT_SCHEDULE"
AFTER INSERT
ON SCHEDULE
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE V_UserCode VARCHAR2(20);
BEGIN
--Find "super user" code.
SELECT UserTypeCode INTO V_UserCode FROM
(SELECT UL.User_Code,
UFT.UserTypeCode,
ROW_NUMBER() OVER (PARTITION BY UL.User_Code ORDER BY UF.UserTypeCode DESC) RN
FROM UserLogin UL
JOIN UserFunction UF
ON UL.User_Code = UF.User_Code
JOIN UserFuncType UFT
ON UFT.UserTypeCode = UF.UserTypeCode
WHERE UFT.FuncType = 'S'
) WHERE RN = 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
V_UserCode := NULL;
IF V_UserCode IS NOT NULL
THEN UPDATE SCHEDULE
SET :NEW.UserTypeCode = V_UserCode,
OrigScheType = :NEW.UserTypeCode
WHERE CompCode = :NEW.CompCode
AND UserTypeCode = :NEW.UserTypeCode
AND ScheOrigin = :NEW.ScheOrigin
AND ScheCode = :NEW.ScheCode;
END IF;
END;
When i try to create the trigger, is returned the fallowing error:
ORA-00922
I'm pretty sure the problem is the UPDATE part, where tried compare in the WHERE clause, the Schedule table keys to be sure of which row i'm updating(inserted), but i could not realize the problem.
In triggers, you don't update tablename set :new.columnname = some value, you directly assign values to :new.columnname using PL/SQL assignments or select into. Therefore, from a syntax point of view, the final update should be replaced with something like:
:new.usertypecode := v_usercode;
:new.origschetype := v_usercode;
(I am assuming the update is only intended to apply to the current row. If the idea is to update multiple rows in the triggering table, you can't do that in a row-level trigger.)
However, this logic doesn't look like it will work:
exception
when no_data_found then
v_usercode := null;
if v_usercode is not null then
v_usercode has to be null at this point, so you don't have a value to set :new.usertypecode to, and I'm not sure what you want the trigger to do.
I need to read data row by row and update it based on the matching case.
My code is just reading ORBREFTND and inserting Refund from case , not reading other cases. What am i doing wrong.
DECLARE
v_tot_rows NUMBER (3);
v_eval ISG.SWR_CERT_TXN_MSG_TYPE.DESC_TX%TYPE;
CURSOR pltfm_msg_type_cur
IS
SELECT sctmt.PLTFM_MSG_TYPE_CD
FROM ISG.SWR_CERT_TXN_MSG_TYPE sctmt
JOIN ISG.FEATURE_VALUES ft_val
ON sctmt.SWR_CERT_FETR_VAL_ID = ft_val.FEATURE_VAL
JOIN ISG.FEATURE_CATEGORY ft_cat
ON ft_val.FEATURE_CAT = ft_cat.FEATURE_CAT
WHERE ft_cat.SHORT_DESCRIP = 'PLT'
AND ft_val.FEATURE_VALUE = 'Orbital';
BEGIN
FOR msg_code IN pltfm_msg_type_cur
LOOP
CASE msg_code.PLTFM_MSG_TYPE_CD
WHEN 'WAC'
THEN
v_eval := 'Authorization and Mark for Capture';
WHEN 'ORBAUTHCAP'
THEN
v_eval := 'Authorization Capture';
WHEN 'ORBREFTND'
THEN
v_eval := 'Refund';
END CASE;
UPDATE ISG.SWR_CERT_TXN_MSG_TYPE sctmt
SET sctmt.DESC_TX = v_eval;
END LOOP;
COMMIT;
v_tot_rows := SQL%ROWCOUNT;
/* Implicit Attribute %ROWCOUNT is used to find the number of rows affected by the update command */
DBMS_OUTPUT.PUT_LINE ('Total records updated : ' || v_tot_rows);
END;
You're missing a where-condition:
UPDATE ISG.SWR_CERT_TXN_MSG_TYPE sctmt
SET sctmt.DESC_TX = v_eval
WHERE sctmt.primarykey = msg_code.primarykey; -- This one is missing. Don't know your primary key..
Without the where you'll always set the value of the last cursor-object to all objects in your table ISG.SWR_CERT_TXN_MSG_TYPE.
You also need to select the key from your table:
CURSOR pltfm_msg_type_cur
IS
SELECT sctmt.PLTFM_MSG_TYPE_CD,
sctmt.PRIMARYKEY -- select key here
FROM ISG.SWR_CERT_TXN_MSG_TYPE sctmt
JOIN ISG.FEATURE_VALUES ft_val
ON sctmt.SWR_CERT_FETR_VAL_ID = ft_val.FEATURE_VAL
JOIN ISG.FEATURE_CATEGORY ft_cat
ON ft_val.FEATURE_CAT = ft_cat.FEATURE_CAT
WHERE ft_cat.SHORT_DESCRIP = 'PLT'
AND ft_val.FEATURE_VALUE = 'Orbital';
i have a table with 4 columns
1.msisdn
2.accountnumber
3.cardnumber
4.subscriptiondate
I want to add a trigger to this table. If the data i am inserting is
1.99999999
2.2
3.3298572857239
4.(this can be blank)
and the data that is currently in the table is
1.99999999
2.1
3.3298572857239
4.(this can be blank)
Trigger should check if there is this msisdn 99999999 is already having a record with this cardnumber 3298572857239. If there is a record already existing in the table, the trigger should delete the existing entry and insert the new one. The final result should look like this
1.99999999
2.1
3.3298572857239
4.(this can be blank)
I want to keep the value of accountnumber same before and after the trigger. This is what i have tried so far but for this trigger, i am not getting any data in accountnumber column. Please someone help
DROP TRIGGER TRIG_TABLEA;
CREATE OR REPLACE TRIGGER TRIG_TABLEA
BEFORE INSERT ON TABLEA
REFERENCING OLD AS Old NEW AS New
FOR EACH ROW
BEGIN
:new.accountnumber := :old.accountnumber;
DELETE FROM TABLEA WHERE MSISDN = :new.MSISDN AND CARDNUMBER = :new.CARDNUMBER;
:new.MSISDN := :new.MSISDN;
:new.CARDNUMBER := :new.CARDNUMBER;
:new.accountnumber := :old.accountnumber;
END;
/
Don't do a delete-and-insert. You want MERGE. The only thing that can change in your statement is accountnumber and subscriptiondate. You don't say where the data is coming from, so I assume this is a PL/SQL procedure with p_* as the parameters. So you want something like this:
MERGE INTO mytable trg
USING ( SELECT p_accountnumber, p_subscriptiondate FROM dual ) src
ON ( trg.msisdn = p_msisdn AND trg.cardnumber )
WHEN NOT MATCHED INSERT ( msisdn, accountnumber, cardnumber, subscriptiondate )
VALUES ( p_msisdn, p_accountnumber, p_cardnumber, p_subscriptiondate )
WHEN MATCHED SET ( cardnumber = p_cardnumber, subscriptiondate = p_subscriptiondate)
This will do an insert if the row doesn't exist or update an existing row if it does.
Please find by below code snippet :
BEGIN
IF (in_config1 IS NOT NULL OR in_config1 !='') THEN
UPDATE question_table
SET comment = in_config1
WHERE id= id
AND questionid = 1;
ELSE
INSERT INTO question_table(
tid
,questionid
,comments)
VALUES( id
, 1
, in_config1);
END IF;
END;
My requirement is to update question_table based on some condition.If update fails which would be incase if record is not present,then i need to add insert statement in the else block.
In the above code update is working. But insert statement is not getting executed.Please let me know whats wrong?
If I understand you, you need upsert statement, where you update if the record match some value, and you insert if it doesn't. The best option can serve you in this case is MERGE clause. It's efficient, flexible and readable. The following is a general script that might need minor changes based on where you are getting the values from and your tables structures.
MERGE INTO question_table a
USING (SELECT id, your_key, in_config1 FROM DUAL) b
ON (a.id = b.id)
WHEN MATCHED THEN
UPDATE question_table
SET comment = in_config1
WHEN NOT MATCHED THEN
INSERT INTO question_table(
tid
,questionid
,comments)
VALUES( id
, 1
, in_config1);
simply you can do like this use sql%notfound
BEGIN
IF (in_config1 IS NOT NULL OR in_config1 != '') THEN
UPDATE question_table
SET comment = in_config1
WHERE id = id
AND questionid = 1;
if sql%notfound then
INSERT INTO question_table (tid, questionid, comments) VALUES (id, 1, in_config1);
end if;
END IF;
exception
when others then
dbms_output.put_line(sqlerrm);
END;
I have the following code which is not executing correctly. I have data stored in date_tmp (varchar) that includes dates and nondates. I want to move the dates in that column to date_run (date) and data that is not a date, will be moved to a comments (varchar) column. When I run the following code, the entire set of data gets moved to comments. It runs fine when I edit out the insert statement and just run the dbms_outputline line. What might I be doing incorrectly?
DECLARE
CURSOR getrow IS
SELECT a.id, a.date_tmp
FROM mycolumn a
WHERE a.id < 1300;
v_date date;
BEGIN
FOR i in getrow LOOP
BEGIN
v_date := to_date(i.date_tmp, 'mm/dd/yy');
INSERT INTO mycolumn a(a.date_run)
VALUES(i.date_tmp);
EXCEPTION
WHEN OTHERS THEN
--dbms_output.put_line(i.date_tmp);
update mycolumn a
SET a.comments = i.date_tmp
where a.id = i.id;
END;
END LOOP;
END;
You try to insert varchar i.date_tmp into a date field. Instead insert v_date.
...
INSERT INTO mycolumn a (a.date_run)
VALUES(v_date);
...
But actually your requirement is a move. That calls for an update actually. So I think what you really want to do is:
...
update mycolumn a
SET a.date_run = v_date
where a.id = i.id
...
And actually you could have a function that checks if you have a valid date or not and then you might be able to handle the whole task using a simple update statement.
create or replace function is_a_date(i_date varchar2, i_pattern varchar2)
return date
is
begin
return to_date(i_date, i_pattern);
exception
when others return null;
end is_a_date;
With that function you could write two update statements
update mycolumn
set date_run = to_date(date_tmp,'dd/mm/yy')
where is_a_date(date_tmp, 'dd/mm/yy') is not null;
update mycolumn
set comment = date_tmp
where is_a_date(date_tmp, 'dd/mm/yy') is null;
I designed the function in a way that you could use it in various ways as it returns you a date or null but no exception if the varchar does not conform to the date pattern.
You have an insert where it looks like you need an update, like you have in the exception handler. So just change it to:
v_date := to_date(i.date_tmp, 'mm/dd/yy');
update mycolumn
set date_run = v_date
where id = i.id;
or you could shorten it to:
update mycolumn
set date_run = to_date(i.date_tmp, 'mm/dd/yy')
where id = i.id;
#hol solution is the best approach for me.
Avoid always you can loops and procedures if you can do it with simple SQL statments, your code will be more faster.
Also, if you have always have a data fixed format , you can ride of the PL/SQL function is_a_date function and do it everything with SQL... but the code gets a little uglier with something like this:
update mycolumn
set date_run = to_date(date_tmp,'dd/mm/yy')
where substr(date_tmp,1,2) between '1' and '31'
and substr(date_tmp,4,2) between '1' and '12'
and substr(date_tmp,7,2) between '00' and '99';
If you need more speed in your query or you have a huge amount of data in date_tmp, as function is_a_date is deterministic (always returns the same value given the same values for X, Y,), you can create an index for it:
create index mycol_idx on mycolumn(is_a_date(date_tmp));
And when you use the function, Oracle will use your index, like in those selects:
SELECT a.id, a.date_tmp
FROM mycolumn a
WHERE a.id < 1300
and is_a_date(a.date_tmp) is not null;
SELECT a.id, a.date_tmp
FROM mycolumn a
WHERE a.id < 1300
and (is_a_date(a.date_tmp) is not null and is_a_date(a.date_tmp)>sysdate-5);