oracle 12c Testing triggers on views - oracle

I have created view in Oracle 12c using the following code:
CREATE VIEW ConcertView AS
SELECT a.ConcertNo, a.Concert_Name, a.Price, a.Duration, a.City, b.EventDate, b.Even t_Name
FROM Concert a,Events b
WHERE a.ConcertNo = b.ConcertNo
AND a.ConcertNo != 'CN002'
The view creates without any errors. I then create a trigger on the view using the following code:
CREATE OR REPLACE TRIGGER check_month
INSTEAD OF DELETE OR INSERT OR UPDATE ON ConcertView
DECLARE
ConcertDate date;
BEGIN
IF (to_char(EventDate, 'DD-MM-YY') = 'JUL') THEN
raise_application_error(-20000, 'Concerts cannot be run during JULY');
END IF;
END;
Trigger created.
The trigger creates without any errors.
I am trying to ensure that concerts cannot be run during July.
However the trigger does not take any action. Could anybody please let me know what I am doing wrong, or explain how to test a trigger?

Replace this sentence:
IF (to_char(EventDate, 'DD-MM-YY') = 'JUL')
For this:
IF to_char(EventDate, 'MON') = 'JUL'
In the first sentence you are comparing the date in the format DD-MM-YY with the name of the month. In the second, you're going to compare the name of the month.
You can check the doc here:
Oracle Doc.

Related

Can I make an update trigger using data from one table to update another?

I'm trying to get the suspension value in my studentstaff table to change from 'no' to 'yes' when the fine (a separate table) amount reaches >=10 for a specific person. I've also tried using IF but nothings seems to be working as I keep getting this error: ORA-04079: invalid trigger specification. "amount NUMBER(8);" is in the code as it was asking me to declare amount. I am using Oracle SQL. Thanks in advance.
CREATE TRIGGER new_suspension
AFTER UPDATE ON fine
FOR EACH ROW
amount NUMBER(8);
BEGIN
CASE
WHEN Amount >= 10 THEN
UPDATE studentstaff
SET suspensions = 'yes'
WHERE library_card_no = '419746';
END CASE;
END;
/
The best option for this type of trigger is to use the when condition on trigger as follows:
CREATE OR REPLACE TRIGGER new_suspension
AFTER UPDATE ON fine
FOR EACH ROW
WHEN (NEW.AMOUNY >= 10)
BEGIN
UPDATE studentstaff
SET suspensions = 'yes'
WHERE library_card_no = :new.LIBRARY_CARD_HOLDER;
END;
/
This trigger will be executed when the condition written in the WHEN clause is satisfied.
Without seeing your table definitions its hard, but here's a guess at what you might need
CREATE OR REPLACE
TRIGGER new_suspension
AFTER UPDATE ON fine
FOR EACH ROW
BEGIN
if :new.Amount >= 10 THEN -- ie, the incoming AMOUNT on the FINE table
UPDATE studentstaff
SET suspensions = 'yes'
WHERE library_card_no = :new.LIBRARY_CARD_HOLDER -- ie, the STUDENT being fined
end if;
END;
/
Hopefully that makes sense and is close to what you're aiming to achieve here. In this example, I'm assuming that your FINE table, contains the amount and the library card holder (ie, the student etc)

Insert inside trigger not firing

Hi i have this simple trigger in oracle
CREATE OR REPLACE TRIGGER OCAP_CREATE_NCRB
BEFORE INSERT
ON OCAP_TBLOCAP
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
Defect_Type varchar2(16);
out_ varchar2(60);
BEGIN
Select A.DEFECT_TYPE into Defect_Type from OCAP_TBLDEFECT A where A.DEFECT_ID = :NEW.DEFECT;
IF Defect_Type = 'C' THEN
--Create NCRB
SP_INSERTTBLD1D2(23,LPAD(:NEW.ISSUED_BY,6,'0'),0,'0','0','035823','Draft',' ',' ',34,' ',0,461,0,0,'035105',trunc(sysdate),' ','A',Lpad(:NEW.ISSUED_BY,6,'0'),Lpad(:NEW.ISSUED_BY,6,'0'),trunc(sysdate),'A',:New.BATCH_NO,out_);
--insert action
SP_INSERTTBLFORMYACTION(Lpad(:NEW.ISSUED_BY,6,'0'), out_, Lpad(:NEW.ISSUED_BY,6,'0'), Lpad(:NEW.ISSUED_BY,'0'), 'Draft');
--Insert other affected Lots
insert into TBLD2LOT(NCRBSERIESNO,LOTNO,CREATEDBY,CREATEDDT,SEQNO) Select (out_), A.BATCH_NO,Lpad(:NEW.ISSUED_BY,6,'0'),sysdate,(TBLD2LOTSEQ.nextval) from OCAP_OTHERBATCH A where A.OCAP_ID = :NEW.OCAP_NO;
--add NCRBSeries no. to table OCAP_TBLOCAP for referencing
Update OCAP_TBLOCAP set NCRBSERIESNO = out_ where OCAP_NO = :NEW.OCAP_NO;
--Insert ocap history
END IF;
END Ocap_Create_NCRB;
/
the first 2 stored procedure is working fine but the insert query is not .
I try to excute the insert query manunaly by replacing the Out_ and the :new.Ocap_no it is working fine.
Is there something wrong in my query?
Hope someone help me out with this.
If it isn't working, then
from OCAP_OTHERBATCH A
where A.OCAP_ID = :NEW.OCAP_NO; --> this condition is never met
which means that no rows in OCAP_OTHERBATCH contain OCAP_ID value which is equal to :NEW.OCAP_NO.
Might be because of wrong letter case, CHAR datatype (right-padded with spaces up to column's full length), ... who knows. Without tables' description and sample data, it is difficult to guess.

Oracle Trigger Conditional Rows

I'am just exploring Trigger in Oracle.
I have table like this
Note : WT_ID Id is FK of Water Summary but not have constraint(not directly connected)
I want to make trigger in Temp_tank table, if there are update in Table Temp_tank, it will sum all temp_tank volume with same WT_ID then updated it to Water_summary.Water_Use. Because of bussiness requirement, not all water_summary data will update. in this example only Home A will be affected
This is MyCode
CREATE OR REPLACE TRIGGER UPD_WaterUse
AFTER UPDATE ON Temp_tank
DECLARE
temp_wat number;
homeA_id= 1;
BEGIN
IF (WT_ID = homeA_id) THEN
SELECT SUM(ss.Volume) INTO temp_wat
from Temp_tank ss WHERE ss.Daytime = DAYTIME and ss.WT_ID =homeA_id;
-- functionUpdate(homeA_id,Daytime,temp_wat) ;
ELSE
NULL;
END IF;
END;
/
The question is, in line
IF (WT_ID = homeA_id) THEN
when i compiled, the line is ignored because WT_ID is not identifier.
is trigger cannot accept this style of code?

Getting Unknown Command error on IF-THEN-ELSE

I have the following query that I am using in Oracle 11g
IF EXISTS (SELECT * FROM EMPLOYEE_MASTER WHERE EMPID='ABCD32643')
THEN
update EMPLOYEE_MASTER set EMPID='A62352',EMPNAME='JOHN DOE',EMPTYPE='1' where EMPID='ABCD32643' ;
ELSE
insert into EMPLOYEE_MASTER(EMPID,EMPNAME,EMPTYPE) values('A62352','JOHN DOE','1') ;
END IF;
On running the statement I get the following output:
Error starting at line : 4 in command -
ELSE
Error report -
Unknown Command
1 row inserted.
Error starting at line : 6 in command -
END IF
Error report -
Unknown Command
The values get inserted with error when I run it directly. But when I try to execute this query through my application I get an oracle exception because of the error generated :
ORA-00900: invalid SQL statement
And hence the values are not inserted.
I am relatively new to Oracle. Please advise on what's wrong with the above query so that I could run this query error free.
If MERGE doesn't work for you, try the following:
begin
update EMPLOYEE_MASTER set EMPID='A62352',EMPNAME='JOHN DOE',EMPTYPE='1'
where EMPID='ABCD32643' ;
if SQL%ROWCOUNT=0 then
insert into EMPLOYEE_MASTER(EMPID,EMPNAME,EMPTYPE)
values('A62352','JOHN DOE','1') ;
end if;
end;
Here you you the update on spec, then check whether or not you found a matching row, and insert in case you didn't.
"what's wrong with the above query "
What's wrong with the query is that it is not a query (SQL). It should be a program snippet (PL/SQL) but it isn't written as PL/SQL block, framed by BEGIN and END; keywords.
But turning it into an anonymous PL/SQL block won't help. Oracle PL/SQL does not support IF EXISTS (select ... syntax.
Fortunately Oracle SQL does support MERGE statement which does the same thing as your code, with less typing.
merge into EMPLOYEE_MASTER em
using ( select 'A62352' as empid,
'JOHN DOE' as empname,
'1' as emptype
from dual ) q
on (q.empid = em.empid)
when not matched then
insert (EMPID,EMPNAME,EMPTYPE)
values (q.empid, q.empname, q.emptype)
when matched then
update
set em.empname = q.empname, em.emptype = q.emptype
/
Except that you're trying to update empid as well. That's not supported in MERGE. Why would you want to change the primary key?
"Does this query need me to add values to all columns in the table? "
The INSERT can have all the columns in the table. The UPDATE cannot change the columns used in the ON clause (usually the primary key) because that's a limitation of the way MERGE works. I think it's the same key preservation mechanism we see when updating views. Find out more.

upgrading 10 g to 11g checklist

There are plenty of stored procedure on 10g platform . ( Almost 500 SPs)
Each SP might have loop, fetch and etc.
I'd like to ask you if there is a cool method to control all the SPs which are currently running on 10g, and guarantee that it works on 11 g.
I have a development server 1 which is 10 g and the other development server is 11 g.
I can use both of them to testify the propose above.
For instance I know that on 10 g if you use loop, and during the loop the update statements do not affect the loop data but 11g.
There might be more cases that I have to consider. Please tell me if you have any brillant idea , otherwise I will check them up one by one manually and it is a lot of time and human control might be weak sometimes.
important note: It is said that if you select some data from a table or tables, and if you use it in a loop, then during de loop, if you update and commit between loop case, it affects the selected data in cursor.(#11g) But this did not happen #10g version. Please correct me if you heard something like that.
The Example Case;
CREATE TABLE vty_musteri(
musterino NUMBER NOT NULL,
subeadi VARCHAR2(61),
kayitzamani VARCHAR2(20)
);
INSERT INTO vty_musteri (musterino, subeadi, kayitzamani )
VALUES (12345, 'AMSTERDAM', '05/30/2012 15:11:13');
COMMIT;
CREATE UNIQUE INDEX vty_musteri_idx ON vty_musteri (musterino);
SELECT * FROM vty_musteri;
CREATE OR REPLACE PROCEDURE krd_upd_silseomusteri_sp(RC1 in out SYS_REFCURSOR) AS
v_musterino NUMBER := 12345;
BEGIN
OPEN RC1 FOR
SELECT m.musterino, m.subeadi, m.kayitzamani
FROM vty_musteri m
WHERE m.musterino = v_musterino;
update vty_musteri
set subeadi = 'PORTO',
kayitzamani = (SELECT TO_CHAR(SYSDATE, 'MM/DD/YYYY HH24:MI:SS')
FROM dual)
where musterino = v_musterino;
COMMIT;
After all run this test on PLSQL:
DECLARE
--test
vRecTip SYS_REFCURSOR;
TYPE vRecTipK IS RECORD(
musterino NUMBER,
subeadi VARCHAR2(61),
kayitzamani VARCHAR2(20)
);
v_SeoTip vRecTipK;
BEGIN
krd_upd_silseomusteri_sp(rc1 => vRecTip);
IF vRecTip%ISOPEN THEN
LOOP
FETCH vRecTip
INTO v_SeoTip;
EXIT WHEN vRecTip%NOTFOUND;
dbms_output.put_line('The Value : ' || v_SeoTip.musterino || ' - ' || v_SeoTip.subeadi || ' - ' || v_SeoTip.kayitzamani);
END LOOP;
END IF;
COMMIT;
END;
END;
If you run this on 10g you will see AMSTERDAM, but on 11G, it is PORTO.
To fix it; I put a hint in the sp like the following:
SELECT /*+ full(m)*/ m.musterino, m.subeadi, m.kayitzamani
Isn't it weird? any alternative sugesstion to get AMSTERDAM ?
One thing we stumbled upon during a migration were queries that weren't supposed to work on 10.x (but did anyway) did no longer work on 11.x
This happens if you have ambigous column references in your query.
Something like this:
SELECT name,
f.some_col,
b.other_col
FROM foo f,
JOIN bar b ON f.id = b.fid
If the column name exists in both tables, 10.x would run the statement - which was a bug.
This bug (BugID: 6760937) was fixed and makes the statement (rightfully) fail in 11.x
Basic PLSQL structures should work exactly the same. Some pitfalls are listed here:
http://www.help2ora.com/index.php/2011/08/04/be-careful-when-migrating-difference-between-oracle-10g-and-11g/
To fix it; I put a hint in the sp like the following:
SELECT /+ full(m)/ m.musterino, m.subeadi, m.kayitzamani
Recently I have done migration to Oracle 11g. Faced few unprecedented issues. I have written a blog post on this. Have a look http://learncodewrite.blogspot.in/2017/04/migrating-to-oracle-11g-from-oracle-10g.html?m=1.

Resources