How to draw the line that triggered the trigger pl/sql? - oracle

This is my code:
CREATE OR REPLACE TRIGGER TR_DEL
AFTER INSERT OR UPDATE
ON DIZIONARIO_CHIAVI_DA_ESCLUDERE
FOR EACH ROW
DECLARE
CURSOR c_cursore_prendi_riga IS
SELECT CURRICULUM_CHIAVE_RICERCA
FROM PERSONA;
myCursor PERSONA.CURRICULUM_CHIAVE_RICERCA%TYPE;
BEGIN
OPEN c_cursore_prendi_riga;
LOOP
FETCH c_cursore_prendi_riga INTO myCursor;
EXIT WHEN c_cursore_prendi_riga%NOTFOUND;
dbms_output.put_line('oo='|| myCursor );
-- Here I need it
END LOOP;
CLOSE c_cursore_prendi_riga;
END;
I need the row that started the trigger, thanks

Nicholas Krasnov is right, to put this in an answer:
:new and :old are used as pseudo-records. Documentation is here:
https://docs.oracle.com/database/121/TDDDG/tdddg_triggers.htm#TDDDG50000
and here the explanation of these pseudo-records:
https://docs.oracle.com/database/121/LNPLS/triggers.htm#LNPLS99955
Most important: pseudo-records can not used like "normal" records. You have to name each column...
For example you can not use:
my_special_function(:new);
You wil have to create a "real" record:
declare
myrec mytable%rowtype;
begin
myrec.id := :new.id;
myrec.name := :new.name;
myrec.birthdate := :new.birthdate;
etc etc etc
my_special_function(myrec);
end

Related

Returning Multiple Columns in stored procedure - ORACLE 11.2 Up

Just wondering how I go about returning multiple columns from the database with this stored proc, Thanks.
is
cursor sample_cur is --this can be your select statement
select name as today from names;
begin
for rec in sample_cur loop
-- step by step for each record you return in your cursor
dbms_output.put_line(rec.name);
end loop;
end;
Cursor can return multiple columns, for example:
procedure list_something(p_result out sys_refcursor) as
begin
open p_result for
select t.column1,
t.column2
from MY_TABLE t
where t.column3 is not null;
end;
Next you can iterate thought this cursor from Java/.Net, etc.
Apart from Manushin's answer, If you strictly wants answer in your format, You may try below -
is
cursor sample_cur is --this can be your select statement
select name, other_column1, other_column2 as today from names;
begin
for rec in sample_cur loop
-- step by step for each record you return in your cursor
dbms_output.put_line(rec.name || rec.other_column1 || rec.other_column2);
end loop;
end;

Assign Value to a Nested Table without Looping

say i have the table XX_TEST_DATA and its being used to populate a nested table inside a PL/SQL block below (please note the comments):
DECLARE
CURSOR XX_DATA_CUR
IS
SELECT *
FROM XX_TEST_DATA;
TYPE TYP_XX_TEST IS TABLE OF XX_TEST_DATA%ROWTYPE INDEX BY PLS_INTEGER;
XX_REC TYP_XX_TEST;
BEGIN
OPEN XX_DATA_CUR;
FETCH XX_DATA_CUR
BULK COLLECT
INTO XX_REC;
CLOSE XX_DATA_CUR;
for i in 1..XX_REC.count loop
XX_REC(i).BATCH_NAME := 'Batch 1'; -- This is the Line
end loop;
END;
I would like to assign the value "Batch 1" to ALL records inside the nested table. Would this be possible without looping through all the records?
Something like below:
BEGIN
OPEN XX_DATA_CUR;
FETCH XX_DATA_CUR
BULK COLLECT
INTO XX_REC;
CLOSE XX_DATA_CUR;
XX_REC.BATCH_NAME := 'Batch 1'; --
END;
I know the above block would not work, but I was hoping to achive something like that.
DDL of the Test Table
Create table XX_TEST_DATA
(
XX_ID NUMBER
, XX_DATA1 VARCHAR2(100)
, XX_DATA2 VARCHAR2(100)
, BATCH_NAME VARCHAR2(100)
);
The value could be set as part of the SELECT and then there would be no need to update the collection.
DECLARE
TYPE TYP_XX_TEST IS TABLE OF XX_TEST_DATA%ROWTYPE INDEX BY PLS_INTEGER;
XX_REC TYP_XX_TEST;
BEGIN
SELECT XX_ID, XX_DATA1, XX_DATA2, 'Batch 1'
BULK COLLECT INTO XX_REC
FROM XX_TEST_DATA;
END;
/

Multiple line output in pl/sql

I have a PL/SQL file that has a loop structure.
The script is as follows.
SET SERVEROUTPUT ON
declare
c_id employee.id%type;
c_name employee.name%type;
c_address employee.address%type;
CURSOR c_employee is
SELECT id, name, address from employee;
begin
open c_employee;
LOOP
FETCH c_employee into c_id, c_name, c_address;
EXIT when c_employee%notfound;
dbms_output.put_line(c_id||' '||c_name||' '||c_address);
END LOOP;
close c_employee;
end;
/
When I run this from SQLPlus I get only the details of the first row but not the rest. What am I doing wrong? How to get all the outputs for the loop.
Try to convert your code to use a for loop instead of the open statement, like so -
for r_employee in c_employee
LOOP
dbms_output.put_line(r_employee.c_id||' '||r_employee.c_name||' '||r_employee.c_address);
END LOOP;
Where r_employee is a variable of employee%type.
The way you currently wrote it does not iterate through the cursor, and this is why only the first row is presented.
Even though your code looks correct, it should iterate through all the
row not just one. Try to use below snippet and run it in SQL plus if
still single row then there may be some other issue.
SET SERVEROUTPUT ON
DECLARE
BEGIN
FOR I IN
(SELECT id, name, address FROM employee
)
LOOP
dbms_output.put_line(I.ID||' '||I.name||' '||I.address);
END LOOP;
END;
/

How do I insert variable values in to a table record in an oracle procedure

How do I insert variable values in to a table record in an oracle procedure?
if pCount1=0 then
insert into opions(qid,otext,oflag)
(rec.pQid, rec.pOptions, rec.pCorrect);
end if;
where rec.* are the variables of the procedure
Are you looking for one of these statements (which are functionally equivalent)?
insert into opions(qid,otext,oflag)
values (rec.pQid, rec.pOptions, rec.pCorrect);
insert into opions(qid,otext,oflag)
select rec.pQid, rec.pOptions, rec.pCorrect from dual;
This assumes that rec is defined somewhere else in the stored procedure. Otherwise, you need to use the second form with rec defined in the from clause.
Try:
CREATE OR REPLACE PROCEDURE SOME_PROC AS
nQid NUMBER;
strOptions VARCHAR2(100);
strCorrect VARCHAR2(1);
BEGIN
nQid := 1;
strOptions := 1234;
strCorrect := 'Y';
INSERT INTO OPIONS(qid, otext, oflag)
VALUES (nQid, strOptions, strCorrect);
END SOME_PROC;
Best of luck.

How to get number of rows affected by a statement when inside that statement's trigger

I have a statement level trigger that fires whenever INSERT UPDATE or DELETE operations are performed on a table (called customers). I want to display a message (to DBMS_OUTPUT) containing the number of rows that were inserted/updated/deleted.
I just want one message for each triggering statement, eg
'4 rows were inserted into customers table'.
How can I access the number of rows that are affected by the triggering statement from INSIDE the trigger declaration, ie XXX in the code below:
CREATE OR REPLACE TRIGGER customer_changes_trigger_2
AFTER INSERT OR UPDATE OR DELETE ON customers
DECLARE
v_operation VARCHAR(10);
v_number_rows NUMBER;
BEGIN
v_number := XXX;
IF INSERTING THEN
v_operation := 'inserted';
END IF;
IF UPDATING THEN
v_operation := 'updated';
END IF;
IF DELETING THEN
v_operation := 'deleted';
END IF;
DBMS_OUTPUT.PUT_LINE
(v_number_rows|| ' rows were ' || v_operation || ' from customers.');
END;
Can't find anything in the documentation, any help appreciated!
One way is to use a global variable to track the number of rows as there is no other way to get the row count from a statement level trigger. You would then need three triggers... one statement level to initialise the variable before the statement is run, one row level to add one to the variable for each row, one statement level to use the row count however you wish. First, set up the variable and a few procedures to help it:
create or replace package PKG_ROWCOUNT is
NUMROWS number;
procedure INIT_ROWCOUNT;
procedure ADD_ONE;
function GET_ROWCOUNT
return number;
end PKG_ROWCOUNT;
/
create or replace package body PKG_ROWCOUNT as
procedure INIT_ROWCOUNT is
begin
NUMROWS := 0;
end;
procedure ADD_ONE is
begin
NUMROWS := Nvl(NUMROWS, 0) + 1;
end;
function GET_ROWCOUNT
return number is
begin
return NUMROWS;
end;
end PKG_ROWCOUNT;
/
The first trigger to initialise the variable:
create or replace trigger CUSTOMER_CHANGES_TRIGGER_1
before insert or update or delete
on CUSTOMERS
begin
PKG_ROWCOUNT.INIT_ROWCOUNT;
end;
The second to update per row:
create or replace trigger CUSTOMER_CHANGES_TRIGGER_2
after insert or update or delete
on CUSTOMERS
for each row
begin
PKG_ROWCOUNT.ADD_ONE;
end;
/
The third to display the total:
create or replace trigger CUSTOMER_CHANGES_TRIGGER_3
after insert or update or delete
on CUSTOMERS
begin
Dbms_output.
PUT_LINE(PKG_ROWCOUNT.GET_ROWCOUNT || ' rows were affected.');
end;
I'm not 100$ sure if it's available inside AFTER trigger body, but you can try examining sql%rowcount

Resources