Update trigger not updating timestamp(update operation) in column - sql

Trigger not working while updating the table column with trigger enabled on table...
CREATE OR REPLACE Trigger TR_FinlStatAssetDesignation_U
BEFORE Update
on FINLSTATASSETDESIGNATION FOR EACH ROW
DECLARE
v_AtDateTime TIMESTAMP(3);
v_LogOperation NUMBER(3,0);
v_UserName VARCHAR2(255);
v_AppName VARCHAR2(255);
SWV_error NUMBER(10,0) DEFAULT 0;
BEGIN
begin
select USERNAME INTO v_UserName FROM v$session WHERE (audsid = SYS_CONTEXT('userenv','sessionid')) AND ROWNUM <=1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
end;
SELECT program INTO v_AppName FROM v$session WHERE audsid=userenv('sessionid');
if (LENGTH(v_AppName) = 0) then
v_AppName := 'Unknown';
end if;
SELECT distinct TO_CHAR(SYSTIMESTAMP,'DD-MON-YY hh24:mi:SS.FF AM') INTO v_AtDateTime FROM dual;
if UPDATING('FinlStatAssetDesignation') then
RAISE_APPLICATION_ERROR(-20000,'Invalid attempt to update OID FinlStatAssetDesignation in FinlStatAssetDesignation');
/*
ROLLBACK */
return;
end if;
if not UPDATING('UpdDate') then
SWV_error := 0;
begin
UPDATE FinlStatAssetDesignation a SET(UpdDate) =(SELECT distinct v_AtDateTime FROM dual where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation)
WHERE ROWID IN(SELECT a.ROWID FROM FinlStatAssetDesignation a where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation);
EXCEPTION
WHEN OTHERS THEN
SWV_error := SQLCODE;
end;
if SWV_error <> 0 then
/*
ROLLBACK */
return;
end if;
end if;
END;
QL> select * from finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 anything 0
01-JAN-17 08.00.00.000000 AM
SQL> update finlstatassetdesignation set finlstatassetdesignationdesc ='nothing';
1 row updated.
SQL> select * from finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 nothing 0
01-JAN-17 08.00.00.000000 AM
SQL> desc finlstatassetdesignation;
Name Null? Type
----------------------------------------- -------- ----------------------------
FINLSTATASSETDESIGNATION NOT NULL CHAR(10 CHAR)
FINLSTATASSETDESIGNATIONDESC NOT NULL VARCHAR2(50 CHAR)
UPDOPERATION NOT NULL NUMBER(10)
UPDDATE NOT NULL TIMESTAMP(6)
Trying to update column FINLSTATASSETDESIGNATIONDESC gets succeded however doesnt update the timestamp in column UPDDATE
Please help....in fixing this trigger...
Trigger not working while updating the table column with trigger enabled on table...

Usually it is a bad idea to write strings (i.e. TO_CHAR(SYSTIMESTAMP,'DD-MM-YY hh24:mi:SS.FF AM') INTO v_AtDateTime) when you actually want to write timestamps.
There are several weak points in your code, according to my understanding you can write it simpler:
CREATE OR REPLACE TRIGGER TR_FinlStatAssetDesignation_U
BEFORE UPDATE
ON FINLSTATASSETDESIGNATION FOR EACH ROW
BEGIN
IF UPDATING('FinlStatAssetDesignation') THEN
RAISE_APPLICATION_ERROR(-20000,'Invalid attempt to update OID FinlStatAssetDesignation in FinlStatAssetDesignation');
-- Rather strange if a column has the same name as the table
END IF;
IF NOT UPDATING('UpdDate') THEN
:NEW.UpdDate := SYSTIMESTAMP;
END IF;
END;
Everything else in your code is redundant, resp. junk.
In case you need the username somewhere, just write USER instead of
select USERNAME INTO v_UserName
FROM v$session
WHERE (audsid = SYS_CONTEXT('userenv','sessionid')) AND ROWNUM <=1;
For application use NVL(SYS_CONTEXT('USERENV', 'CLIENT_PROGRAM_NAME'), 'Unknown') instead of
SELECT program INTO v_AppName FROM v$session WHERE audsid=userenv('sessionid');
if (LENGTH(v_AppName) = 0) then
v_AppName := 'Unknown';
end if;

Related

Is ORA-01403 being received by the procedure or the package being called within the procedure?

Sorry to paste the long code. I have a procedure that inserts data in a table and calls several packages. On running the below procedure, I get following error -
Now I know that the error is coming at stage 3 where package PKG_CM_ACTIONS.P_NEW_CASE_NOTIFY is being called. My questions are -
Is the ORA 01403 being thrown because there is no data to call PKG_CM_ACTIONS.P_NEW_CASE_NOTIFY?
The ORA 01403 is being thrown because PKG_CM_ACTIONS.P_NEW_CASE_NOTIFY is getting called but not returning anything.
Code :
create or replace PROCEDURE P_BNS_CREATE_CASE_MNUL
IS
L_CASE_INTRL_ID VARCHAR2(15);
L_STAGE NUMBER;
L_ERROR_CODE NUMBER;
L_ERROR_MSG VARCHAR2(4000);
TYPE R_PARAMS IS RECORD (
CUSTOMER_ID VARCHAR2(50),
CUSTOMER_TYPE VARCHAR2(50),
SCORE_CT NUMBER(6),
PRIORITY_CD VARCHAR2(20),
JRSDCN_DESC VARCHAR2(50),
CASE_TITL_NM VARCHAR2(200),
CASE_TYPE_CD VARCHAR2(20),
CASE_SUBTYPE_CD VARCHAR2(20),
OWNER_ID NUMBER(10),
ASSIGNED_TO_ID NUMBER(10),
SYSTEM_ID NUMBER(10)
);
TYPE T_PARAMS IS TABLE OF R_PARAMS INDEX BY PLS_INTEGER;
L_PARAMS T_PARAMS;
BEGIN
L_STAGE := 1;
SELECT CUSTOMER_ID, t3.CODE_VAL, SCORE_CT, PRIORITY_CD, t2.JRSDCN_CD, CASE_TITL_NM, CASE_TYPE_CD, CASE_SUBTYPE_CD, T5.OWNER_SEQ_ID, T6.OWNER_SEQ_ID, T7.OWNER_SEQ_ID
BULK COLLECT INTO L_PARAMS
FROM TB_BNS_CREATE_CASE_MNUL t1 LEFT JOIN KDD_JRSDCN t2
ON upper(t1.JRSDCN_DESC) = upper(t2.JRSDCN_DESC_TX)
LEFT JOIN KDD_CODE_SET_TRNLN t3
ON upper(t1.CUSTOMER_TYPE) = upper(t3.CODE_DISP_TX) AND t3.CODE_SET = 'CustomerType'
LEFT JOIN KDD_REVIEW_OWNER t5
ON upper(t1.OWNER_ID) = upper(t5.OWNER_DSPLY_NM)
LEFT JOIN KDD_REVIEW_OWNER t6
ON upper(t1.ASSIGNED_TO_ID) = upper(t6.OWNER_DSPLY_NM)
LEFT JOIN KDD_REVIEW_OWNER t7
ON upper(t7.OWNER_ID) = 'SYSTEM'
WHERE CASE_INTRL_ID IS NULL;
FOR INDX IN 1 .. L_PARAMS.COUNT LOOP
L_STAGE := 1.1;
SELECT PARAM_VALUE_TX||CM_CASES_SEQ.NEXTVAL INTO L_CASE_INTRL_ID
FROM KDD_INSTALL_PARAM WHERE PARAM_ID=17; /*this statement also returns results */
L_STAGE := 2;
INSERT INTO KDD_CASES (ID,NAME,...) VALUES (....,...,....);
L_STAGE := 3;
PKG_CM_ACTIONS.P_NEW_CASE_NOTIFY(L_CASE_INTRL_ID, 'SYSTEM', '0', L_PARAMS(INDX).SCORE_CT, L_PARAMS(INDX).CUSTOMER_ID, 'a', L_PARAMS(INDX).CASE_SUBTYPE_CD);
L_STAGE := 4;
PKG_CM_TABS.P_KYC_MANUAL_CASE_INS(L_CASE_INTRL_ID, L_PARAMS(INDX).CUSTOMER_ID, L_PARAMS(INDX).SCORE_CT);
L_STAGE := 5;
PKG_CM_TABS.P_UPDATE_CASE_DUEDT('CA9', L_CASE_INTRL_ID);
L_STAGE := 6;
UPDATE TB_BNS_CREATE_CASE_MNUL
SET CASE_INTRL_ID = L_CASE_INTRL_ID
WHERE CUSTOMER_ID = L_PARAMS(INDX).CUSTOMER_ID AND CASE_TYPE_CD = L_PARAMS(INDX).CASE_TYPE_CD;
END LOOP;
--COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
L_ERROR_CODE := SQLCODE;
L_ERROR_MSG := SQLERRM;
DBMS_OUTPUT.PUT_LINE (L_ERROR_CODE||' - Error occured at stage -'||L_STAGE||' - '||L_ERROR_MSG);
END P_BNS_CREATE_CASE_MNUL;
[1]: https://i.stack.imgur.com/Lde3j.png
this means that PKG_CM_ACTIONS.P_NEW_CASE_NOTIFY function/procedure probably has SELECT query which does not return any data:
SELECT Id into MyVariable
From Table1
Where 1=0
the above query gives NO_DATA_FOUND error because there is no Id which can be assigned into MyVariable.
If you take a closer look to your error, the error gives the exact line that the error occurs so that you can check the erranous SQL.

check if values exist in table - trigger

I am trying to write trigger which will control if a record is already in table or not. If is the record already in table (compare for example by name), so current record set valid='False' and insert new. Is there any way?
This is my idea, but it doesn't work.
create or replace TRIGGER
Check_r
before insert on t$customer
FOR each ROW
declare
v_dup number;
v_com number;
v_id number;
v_id_new number;
begin
v_date:=SYSDATE;
select count(id) INTO v_dup from t$customer where surname=:NEW.surname ;
select count(id) INTO v_com from t$customer where firstname =:NEW.firstname and
address=:NEW.address;
select id into v_id from t$customer where surname=:NEW.surname;
if v_dup > 0 and v_com=0 then
v_id_new:= m$_GET_ID; -- get id
update t$customer set valid = 'False' where id = v_id;
insert into t$customer ( id, surname ,firstname, valid, address ) values (v_id_new,:NEW.surname ,:NEW.firstname, :NEW.valid, :NEW.address);
end if;
if v_dup = 0 then
v_id_new:= m$_GET_ID; -- get id
insert into t$customer ( id, surname ,firstname, valid , address) values (v_id_new,:NEW.surname ,:NEW.firstname, :NEW.valid, :NEW.address);
end if;
end;
You can use a compound trigger, for example:
CREATE OR REPLACE TRIGGER Check_r
FOR INSERT ON t$customer
COMPOUND TRIGGER
TYPE customerRecordType IS RECORD(
surname t$customer.surname%TYPE,
firstname t$customer.firstname%TYPE,
address t$customer.address%TYPE,
ID nubmer);
TYPE customerTableType IS TABLE OF customerRecordType;
customerTable customerTableType := customerTableType();
n NUMBER;
BEFORE STATEMENT IS
BEGIN
customerTable.DELETE; -- not requried, just for better understanding
END STATEMENT;
BEFORE EACH ROW IS
BEGIN
customerTable.EXTEND;
customerTable(customerTable.LAST).surname := :NEW.surname;
customerTable(customerTable.LAST).firstname := :NEW.firstname;
customerTable(customerTable.LAST).address := :NEW.address;
customerTable(customerTable.LAST).ID := m$_GET_ID;
:NEW.ID := customerTable(customerTable.LAST).ID;
END BEFORE EACH ROW;
AFTER STATEMENT IS
BEGIN
FOR i IN customerTable.FIRST..customerTable.LAST LOOP
SELECT COUNT(*) INTO n
FROM t$customer
WHERE surname = customerTable(i).surname;
IF n > 1 THEN
UPDATE t$customer
SET valid = 'False'
WHERE surname = customerTable(i).surname;
END IF;
SELECT COUNT(*) INTO n
FROM t$customer
WHERE firstname = customerTable(i).firstname
AND address = customerTable(i).address;
IF n > 1 THEN
UPDATE t$customer
SET valid = 'False'
WHERE firstname = customerTable(i).firstname
AND address = customerTable(i).address
END IF;
END LOOP;
END AFTER STATEMENT;
END;
/
Please note, this solution is ugly and poor in terms of performance!
But it should give you an impression how it works.
In general you should put all this into a PL/SQL Procedure instead of a trigger.
First, this is trigger for insert. you don't need to write insert statement.
Second, you need to update old record. Just update it with your where clause.
CREATE OR REPLACE TRIGGER Check_r
before insert on t$customer
FOR each ROW
BEGIN
UPDATE t$customer set valid = 'False'
WHERE surname = :NEW.surname
AND firstname =:NEW.firstname;
:NEW.id := m$_GET_ID;
END;

PL/SQL if table not exist create

Hello i use oracle SQL developer
I have create a procedure, and i need to check if a table exist, if not exist i must create how can do?
I have try this
DECLARE v_emp int:=0;
BEGIN
SELECT count(*) into v_emp FROM dba_tables;
if v_emp = 0 then
EXECUTE IMMEDIATE 'create table EMPLOYEE ( ID NUMBER(3), NAME VARCHAR2(30) NOT NULL)';
end if;
END;
but give me an error 00103 because not find table
Just execute the create and watch the exception if thrown. Oracle would never replace the DDL of a table.
declare
error_code NUMBER;
begin
EXECUTE IMMEDIATE 'CREATE TABLE EMPLOYEE(AGE INT)';
exception
when others then
error_code := SQLCODE;
if(error_code = -955)
then
dbms_output.put_line('Table exists already!');
else
dbms_output.put_line('Unknown error : '||SQLERRM);
end if;
end;
You can run this for example:
if (select count(*) from all_tables where table_name = 'yourTable')>0 then
-- table exists
else
-- table doesn't exist
end if;
You should try following,
declare
nCount NUMBER;
v_sql LONG;
begin
SELECT count(*) into nCount FROM dba_tables where table_name = 'EMPLOYEE';
IF(nCount <= 0)
THEN
v_sql:='
create table EMPLOYEE
(
ID NUMBER(3),
NAME VARCHAR2(30) NOT NULL
)';
execute immediate v_sql;
END IF;
end;

Trigger compilation error

I need some help in creating a trigger.
create or replace trigger trigger_one
before insert on Funtom_timesheet
for each row
Declare
V_id number;
V_hours number;
Begin
Select max(timesheet_ID)+1 into v_id from Funtom_timesheet
:new.timesheet_ID :=v_id;
select grade_hours into V_hours
from funtom_grade join funtom_employee
on emp_grade = grade_id
where empid = :new.timesheet_emp;
if V_hours >:new.timesheet_hours
else
:new.timesheet_overtime :=
:new.timesheet_hours-V_hours
:new.timesheet_hours:= V_hours;
END IF;
END;
/
please tell me which part of my code is wrong so I could work on it,
Thanks
You have many syntax errors - missing ; and then. There can't be if only with else part and without expression on it.
CREATE OR REPLACE TRIGGER TRIGGER_ONE
BEFORE INSERT ON FUNTOM_TIMESHEET
FOR EACH ROW
DECLARE
V_ID NUMBER;
V_HOURS NUMBER;
BEGIN
SELECT MAX(TIMESHEET_ID) + 1 INTO V_ID FROM FUNTOM_TIMESHEET;
:NEW.TIMESHEET_ID := V_ID;
SELECT GRADE_HOURS
INTO V_HOURS
FROM FUNTOM_GRADE
JOIN FUNTOM_EMPLOYEE
ON EMP_GRADE = GRADE_ID
WHERE EMPID = :NEW.TIMESHEET_EMP;
IF V_HOURS > :NEW.TIMESHEET_HOURS THEN
NULL;
ELSE
:NEW.TIMESHEET_OVERTIME := :NEW.TIMESHEET_HOURS - V_HOURS;
:NEW.TIMESHEET_HOURS := V_HOURS;
END IF;
END;
/
Also better use SEQUENCES instead of:
SELECT MAX(TIMESHEET_ID) + 1 INTO V_ID FROM FUNTOM_TIMESHEET;
:NEW.TIMESHEET_ID := V_ID;
When selecting form the same table as inserting, you can get MUTATING trigger error (http://www.dba-oracle.com/t_avoiding_mutating_table_error.htm)

using a select query to create a record in plsql

Probably a really easy question but I created a record that has 3 columns. The third column I am going to assign a value later. The query selects 2 columns for the record. What am I missing? The error that is thrown is that there are "too many values" in my select statment.
create or replace Procedure Pledges3
(IDdonor In Int, flag Out Varchar)
as
type allPledges is record(iddonor dd_pledge.iddonor%type, idstatus dd_status.idstatus%type, flag Varchar(25));
allPledges2 allpledges;
Begin
Select dd_pledge.iddonor, dd_status.idstatus
into allpledges2
from dd_donor
join dd_pledge on dd_donor.iddonor=dd_pledge.iddonor
join dd_status on dd_pledge.idstatus=dd_status.idstatus
where dd_pledge.IDdonor=305;
if allpledges2.idstatus = '10' THEN
Flag := 'True';
elsif allpledges2.idstatus= '20' THEN
Flag := 'False';
End if;
dbms_output.put_line(flag);
End;
Check the below code, corrected:
create or replace Procedure Pledges3
(IDdonor In Int, flag Out Varchar)
as
type allPledges is record(iddonor dd_pledge.iddonor%type, idstatus dd_status.idstatus%type, flag Varchar(25));
allPledges2 allpledges;
Begin
Select dd_pledge.iddonor, dd_status.idstatus, null
into allpledges2
from dd_donor
join dd_pledge on dd_donor.iddonor=dd_pledge.iddonor
join dd_status on dd_pledge.idstatus=dd_status.idstatus
where dd_pledge.IDdonor=305;
if allpledges2.idstatus = '10' THEN
allPledges2.Flag := 'True';
elsif allpledges2.idstatus= '20' THEN
allPledges2.Flag := 'False';
End if;
dbms_output.put_line(allPledges2.flag);
End;