PLSQL trigger to raise application error not working - oracle

I'm trying to create a trigger which raise error if the total number of row exceeds 10, The plsql code was successfully compiled but it's not generating any error.
This is the plsql code:
SQL> CREATE OR REPLACE TRIGGER customer_count_check
2 BEFORE INSERT OR UPDATE ON customer2
3 FOR EACH ROW
4 DECLARE
5 count_customer NUMBER;
6 max_customer NUMBER := 10;
7 BEGIN
8 SELECT COUNT(*) INTO count_customer FROM customer2 WHERE cusid = :new.cusid;
9 IF count_customer >= max_customer THEN
10 RAISE_APPLICATION_ERROR (-20000,'Customer Table capacity exceeded');
11 END IF;
12 END;
13 /

i would say your trigger does't work as you expect, because your select statement inside return always one row.
you filter on a primary key!
that should work
SQL> CREATE OR REPLACE TRIGGER customer_count_check
2 BEFORE INSERT OR UPDATE ON customer2
3 FOR EACH ROW
4 DECLARE
5 count_customer NUMBER;
6 max_customer NUMBER := 10;
7 BEGIN
8 SELECT COUNT(*) INTO count_customer FROM customer2; --WHERE cusid = :new.cusid;
9 IF count_customer >= max_customer THEN
10 RAISE_APPLICATION_ERROR (-20000,'Customer Table capacity exceeded');
11 END IF;
12 END;
13 /

Related

I want to fetch column values from column name rollnoofstud of tableA using PL/SQL

DECLARE
TYPE norollno IS TABLE OF VARCHAR2(100);
rollno norollno;
BEGIN
BEGIN
SELECT token
BULK COLLECT INTO rollno
FROM tableA
WHERE columname='rollnoofstud';
EXCEPTION
WHEN NO_DATA_FOUND THEN
rollno := norollno();
END ;
IF rollno >0 THEN
FOR i IN rollno.FIRST..norollno.LAST
LOOP
<doSomeThing>
END LOOP;
END IF;
END;
I am trying this but I am not getting output. I doubt if my select statement is correct.
I don't have your table so I created one:
SQL> CREATE TABLE tablea
2 AS
3 SELECT ename AS token, 'rollnoofstud' AS columname
4 FROM emp
5 WHERE deptno = 10;
Table created.
Code you posted isn't that wrong; requires a little bit of fixing (see line #17, the way you check whether collection contains something (count it!); typo in FOR loop):
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 TYPE norollno IS TABLE OF VARCHAR2 (100);
3
4 rollno norollno;
5 BEGIN
6 BEGIN
7 SELECT token
8 BULK COLLECT INTO rollno
9 FROM tableA
10 WHERE columname = 'rollnoofstud';
11 EXCEPTION
12 WHEN NO_DATA_FOUND
13 THEN
14 rollno := norollno ();
15 END;
16
17 IF rollno.COUNT > 0
18 THEN
19 FOR i IN rollno.FIRST .. rollno.LAST
20 LOOP
21 DBMS_OUTPUT.put_line (rollno (i));
22 END LOOP;
23 END IF;
24 END;
25 /
CLARK --> here's the result
KING
MILLER
PL/SQL procedure successfully completed.
SQL>
[EDIT: with your sample table and data:]
(note that there's no text datatype in Oracle!)
SQL> CREATE TABLE students
2 (
3 rollnostud INTEGER PRIMARY KEY,
4 name VARCHAR2 (10) NOT NULL,
5 gender VARCHAR2 (1) NOT NULL
6 );
Table created.
SQL> INSERT INTO students
2 VALUES (1, 'Ryan', 'M');
1 row created.
SQL> INSERT INTO students
2 VALUES (2, 'Joanna', 'F');
1 row created.
SQL> INSERT INTO students
2 VALUES (3, 'John', 'M');
1 row created.
Procedure:
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2 TYPE norollno IS TABLE OF VARCHAR2 (100);
3
4 rollno norollno;
5 BEGIN
6 BEGIN
7 SELECT name
8 BULK COLLECT INTO rollno
9 FROM students;
10 EXCEPTION
11 WHEN NO_DATA_FOUND
12 THEN
13 rollno := norollno ();
14 END;
15
16 IF rollno.COUNT > 0
17 THEN
18 FOR i IN rollno.FIRST .. rollno.LAST
19 LOOP
20 DBMS_OUTPUT.put_line (rollno (i));
21 END LOOP;
22 END IF;
23 END;
24 /
Ryan
Joanna
John
PL/SQL procedure successfully completed.
SQL>

How to use this trigger on table?

I am not able to get the value of variable v when I fire this trigger on my table:
create or replace trigger tri
after insert or update or delete on site_sector
declare
v number;
begin
if inserting then
v:=sql%rowcount;
dbms_output.put_line('There is :'||v||' row affected');
elsif updating then
v:=sql%rowcount;
dbms_output.put_line('There is :'||v||' row affected');
elsif deleting then
v:=sql%rowcount;
dbms_output.put_line('There is :'||v||' row affected');
else
dbms_output.put_line('There is no row affected');
end if;
end;
Well, that won't work; something like this might.
Sample table:
SQL> desc test
Name Null? Type
----------------------------------------------------- -------- -----------------
ID NUMBER
Compound trigger: declare a variable which will be incremented in BEFORE EACH ROW; number of rows affected is then displayed in AFTER STATEMENT.
SQL> create or replace trigger tri
2 for insert or update or delete on test
3 compound trigger
4
5 g_cnt number := 0;
6
7 before each row is
8 begin
9 g_cnt := g_cnt + 1;
10 end before each row;
11
12 after statement is
13 begin
14 dbms_output.put_line('Number of rows affected = ' || g_cnt);
15 end after statement;
16 end;
17 /
Trigger created.
Testing:
SQL> insert into test (id)
2 select level from dual connect by level <= 5;
Number of rows affected = 5
5 rows created.
SQL> update test set id = id + 10 where id <= 3;
Number of rows affected = 3
3 rows updated.
SQL> delete from test where id < 10;
Number of rows affected = 2
2 rows deleted.
SQL>
Messages "match"; that's why I wonder where you'll be using this, as Oracle shows that info anyway.

How to update ref cursor values in oracle?

I want to fetch limited no. of rows using refcursor. then I need to update same set of records. is it possible?
create or replace PROCEDURE myproc (
P_ROWCOUNT IN NUMBER,
OUT_TXN_IDS OUT OF_CR_TYPE,
P_CD_ERROR OUT NUMBER,
P_DS_ERROR OUT VARCHAR2
)
AS
V_TXNID NUMBER;
BEGIN
P_CD_ERROR := 0;
P_DS_ERROR := 'SUCCESS';
OPEN OUT_TXN_IDS for
SELECT id FROM table1 WHERE status='N' AND ROWNUM<=P_ROWCOUNT;
EXCEPTION
WHEN OTHERS THEN
P_CD_ERROR := sqlcode;
P_DS_ERROR := 'WF-ERROR - myproc - ' || substr(SQLERRM, 1, 200);
RETURN;
END myproc;
I need to update same records to status Y after refcursor returns. can we do this. please suggest
I don't have your tables nor data so I simplified it a little bit, but - it should work nonetheless.
Initial statuses:
SQL> SELECT status, count(*) FROM table1 group by status;
S COUNT(*)
- ----------
Y 7
N 7
Procedure: basically, you'd modify rows represented by ID returned by ref cursor.
SQL> DECLARE
2 out_txn_ids SYS_REFCURSOR;
3 p_rowcount NUMBER := 5;
4 l_id table1.id%TYPE;
5 BEGIN
6 OPEN out_txn_ids FOR SELECT id
7 FROM table1
8 WHERE status = 'N'
9 AND ROWNUM <= p_rowcount;
10
11 LOOP
12 FETCH out_txn_ids INTO l_id;
13
14 EXIT WHEN out_txn_ids%NOTFOUND;
15
16 UPDATE table1
17 SET status = 'Y'
18 WHERE id = l_id;
19 END LOOP;
20
21 CLOSE out_txn_ids;
22 END;
23 /
PL/SQL procedure successfully completed.
Result:
SQL> SELECT status, count(*) FROM table1 group by status;
S COUNT(*)
- ----------
Y 12
N 2
SQL>

How to execute 2 Store Procedures with conditions

I want to RUN SP2 inside SP1. The SP2 inserts several data into a table, one of those data is actual date.
So, i want that SP2 only execute if in the column date, the date is within the last 10 days.
It´s possible?
Thanks
Here's an example.
First, create a table and insert some sample rows:
SQL> create table my_tbl
2 (id number,
3 my_col date
4 );
Table created.
SQL> insert into my_tbl (id, my_col)
2 -- more than 10 days ago
3 select 1, date '2018-05-25' from dual union all
4 -- less than 10 days ago
5 select 2, date '2018-09-01' from dual;
2 rows created.
Create two procedures; SP_1 is supposed to call SP_2 if condition is met. I'm looping through both rows in the table; one row's date value is OK, another one isn't.
SQL> create or replace procedure sp_2 as
2 begin
3 dbms_output.put_line('...I am in SP_2 now');
4 end;
5 /
Procedure created.
SQL> create or replace procedure sp_1 as
2 begin
3 for cur_r in (select my_col from my_tbl order by id) loop
4 dbms_output.put_line('date value = ' || to_char(cur_r.my_col, 'yyyy-mm-dd'));
5 if cur_r.my_col >= trunc(sysdate) - 10 then
6 dbms_output.put_line('...calling SP_2');
7 sp_2;
8 else
9 dbms_output.put_line('...date condition failed - not calling SP_2');
10 end if;
11 end loop;
12 end;
13 /
Procedure created.
Testing:
SQL> set serveroutput on
SQL> begin
2 sp_1;
3 end;
4 /
date value = 2018-05-25
...date condition failed - not calling SP_2
date value = 2018-09-01
...calling SP_2
...I am in SP_2 now
PL/SQL procedure successfully completed.

Oracle Delete Statement: how many rows have been deleted by cascade delete

I'm executing a statement like
DELETE FROM USER WHERE USER_ID=1;
In SQLDeveloper.
As the user is referenced in many tables (for example the user has an order, settings, ...) we activated ON DELETE CASCADE so that we do not have to delete each and every row manually. However while developing we are interested to know how many rows and and in which tables are "automatically" deleted by cascade delete.
Is there any way to find this out. Either by SQL-Statement, directly in sqldeveloper from a logfile or any other idea?
whilst this is not possible with sql%rowcount, it is possible if you write trigger code, but this means that you need a trigger on all tables you want to monitor. Also triggers would slow down operations a bit.
e.g.:
SQL> select * from one;
ID
----------
1
2
SQL> select * from child_of_one;
ID O_ID
---------- ----------
1 1
2 1
3 1
4 2
5 2
6 2
7 2
8 2
we want a package spec to hold an array of tables + counts:
SQL> create or replace package foo
2 as
3 type rowcount_tab is table of pls_integer index by varchar2(30);
4 t_rowcount rowcount_tab;
5 end foo;
6 /
Package created.
we want a trigger on the top level table to reset these counts to zero:
SQL> create or replace trigger one_biud
2 before insert or update or delete
3 on one
4 declare
5 begin
6 foo.t_rowcount.delete;
7 end;
8 /
Trigger created.
this assumes that you're only interested in the array with a delete from the top level table. if not, you'd want a trigger on each table with foo.t_rowcount.delete('TABLE_NAME') instead.
now a after for each row trigger on each table of interest to set the arrays:
SQL> create or replace trigger one_aiudfer
2 after insert or update or delete
3 on one
4 for each row
5 declare
6 begin
7 if (foo.t_rowcount.exists('ONE'))
8 then
9 foo.t_rowcount('ONE') := nvl(foo.t_rowcount('ONE'), 0)+1;
10 else
11 foo.t_rowcount('ONE') := 1;
12 end if;
13 end;
14 /
Trigger created.
SQL> create or replace trigger child_of_one_aiudfer
2 after insert or update or delete
3 on child_of_one
4 for each row
5 declare
6 begin
7 if (foo.t_rowcount.exists('CHILD_OF_ONE'))
8 then
9 foo.t_rowcount('CHILD_OF_ONE') := nvl(foo.t_rowcount('CHILD_OF_ONE'), 0)+1;
10 else
11 foo.t_rowcount('CHILD_OF_ONE') := 1;
12 end if;
13 end;
14 /
Trigger created.
now when we delete or whatever:
SQL> delete from one where id = 1;
1 row deleted.
SQL> declare
2 v_table varchar2(30);
3 begin
4 v_table := foo.t_rowcount.first;
5 loop
6 exit when v_table is null;
7 dbms_output.put_line(v_table || ' ' || foo.t_rowcount(v_table) || ' rows');
8 v_table := foo.t_rowcount.next(v_table);
9 end loop;
10 end;
11 /
CHILD_OF_ONE 3 rows
ONE 1 rows
PL/SQL procedure successfully completed.
SQL> delete from one where id = 2;
1 row deleted.
SQL> declare
2 v_table varchar2(30);
3 begin
4 v_table := foo.t_rowcount.first;
5 loop
6 exit when v_table is null;
7 dbms_output.put_line(v_table || ' ' || foo.t_rowcount(v_table) || ' rows');
8 v_table := foo.t_rowcount.next(v_table);
9 end loop;
10 end;
11 /
CHILD_OF_ONE 5 rows
ONE 1 rows

Resources