Not able to get get output - plsql

declare
num number(5);
rev number(5);
temp number(5);
begin
num:=#
while num>0
loop
temp:=mod(num,10);
rev:=(rev*10)+temp;
num:=trunc(num/10);
end loop;
dbms_output.put_line('reversed no:' || rev);
end;
OUTPUT:
Enter value for num: 456
old 6: num:=#
new 6: num:=456;
reversed no:
PL/SQL procedure successfully completed.
if have used set serveroutput on;
i am using oracle 11g.
i tried every thing i can think of still having this problem.

The issue lies in the line:
rev := (rev * 10) + temp;
At the point that line is called, rev is null. When you apply mathematical operators to a null value in Oracle, the result is always null.
You can get around this by assigning a value when you declare the variable, i.e.:
DECLARE
num NUMBER(5);
rev NUMBER(5) := 0;
temp NUMBER(5);
BEGIN
num := #
WHILE num > 0
LOOP
temp := MOD(num, 10);
rev := (rev * 10) + temp;
num := trunc(num / 10);
END LOOP;
dbms_output.put_line('reversed no: ' || rev);
END;
/
reversed no: 654

Related

Bulk collect and forall with dynamic query

Declare
Vquery varchar2(32000);
Vitem varchar2(50);
Vskuloc varchar2(50);
vstartdate Date;
Vdur Number;
vtype Number;
vqty Float(126);
GP_ohpost Date:= fnc_ohpost;
sdate1 Date:= to_date('01/01/1970','dd/mm/yyyy');
Cursor C_DRIVER is
(Select h.*,b.item,b.skuloc,h.rowid
FROM SCPOMGR.histwide h, SCPOMGR.dfutosku b
WHERE h.dmdunit=b.dmdunit
AND h.loc=b.dfuloc
AND (b.eff = Sdate1 OR b.eff <= h.startdate
AND b.disc = Sdate1 OR b.disc > h.startdate)
And NOT EXISTS (SELECT 1 FROM SCPOMGR.SKUHIST d
WHERE b.dmdunit = d.item
AND b.skuloc = d.loc
AND h.startdate = d.startdate
)) order by h.StartDate;
TYPE GP_cursor_Type IS TABLE OF C_DRIVER%ROWTYPE;
GP_cursor_tab GP_cursor_Type := GP_cursor_type();
c_limit constant PLS_INTEGER DEFAULT 10;
TYPE GP_Insert_type IS TABLE OF scpomgr.skuhist%ROWTYPE;
GP_Insert_tab GP_Insert_type := GP_Insert_type();
GP_tot_accept_fetched NUMBER := 0;
begin
OPEN C_DRIVER;
LOOP
FETCH c_driver BULK COLLECT INTO GP_cursor_tab limit c_limit;
Exit when c_driver%NOTFOUND;
FOR i IN GP_cursor_tab.FIRST .. GP_cursor_tab.LAST LOOP
vquery:= 'Select ...<skipped to make post shortest>';
Execute immediate vquery BULK COLLECT INTO GP_Insert_tab;
FORALL i IN INDICES OF GP_Insert_tab
Insert into scpomgr.skuhist
values( GP_Insert_tab(i).startdate
,1
,10080
,GP_Insert_tab(i).qty
,GP_Insert_tab(i).item
,GP_Insert_tab(i).loc
);
End Loop;
End Loop;
Close C_DRIVER;
END;
/
What i want to do here is i want to use the forall query outside of loop but if i am using the forall with the 2 nd array outside the loop then.all of the records are not getting inserted to the final table..please suggest me some solution....
Ankita.
I didn't know the structure of your tables, so i made a simple tables to understand what should work here:
create table histwide (f1 number);
insert into histwide values (1);
insert into histwide values (2);
create table skuhist (f1 number);
select * from histwide
select * from skuhist
Now i changed your code keeping changed code in comments. Seems it works. I think the trouble was because of you are used Exit when c_driver%NOTFOUND; in begining of loop. It is wrong for FORALL because after first fetching cursor is empty (if limit is reached).
So, my solution of your case:
Declare
Vquery varchar2(32000);
Vitem varchar2(50);
Vskuloc varchar2(50);
vstartdate Date;
Vdur Number;
vtype Number;
vqty Float(126);
GP_ohpost Date:= trunc(sysdate); --fnc_ohpost;
sdate1 Date:= to_date('01/01/1970','dd/mm/yyyy');
Cursor C_DRIVER is
(Select h.*--,b.item,b.skuloc,h.rowid
--FROM SCPOMGR.histwide h, SCPOMGR.dfutosku b
FROM histwide h
/*WHERE h.dmdunit=b.dmdunit
AND h.loc=b.dfuloc
AND (b.eff = Sdate1 OR b.eff <= h.startdate
AND b.disc = Sdate1 OR b.disc > h.startdate)
And NOT EXISTS (SELECT 1 FROM SCPOMGR.SKUHIST d
WHERE b.dmdunit = d.item
AND b.skuloc = d.loc
AND h.startdate = d.startdate
)) order by h.StartDate*/
);
TYPE GP_cursor_Type IS TABLE OF C_DRIVER%ROWTYPE;
GP_cursor_tab GP_cursor_Type := GP_cursor_type();
c_limit constant PLS_INTEGER DEFAULT 10;
TYPE GP_Insert_type IS TABLE OF skuhist%ROWTYPE; --scpomgr.skuhist%ROWTYPE;
GP_Insert_tab GP_Insert_type := GP_Insert_type();
GP_tot_accept_fetched NUMBER := 0;
begin
OPEN C_DRIVER;
LOOP
FETCH c_driver BULK COLLECT INTO GP_cursor_tab limit c_limit;
Exit when GP_cursor_tab.count = 0;
dbms_output.put_line('arr cur size: '||GP_cursor_tab.count);
FOR i IN GP_cursor_tab.FIRST .. GP_cursor_tab.LAST LOOP
vquery:= 'Select * from histwide';
Execute immediate vquery BULK COLLECT INTO GP_Insert_tab;
dbms_output.put_line('arr size: '||GP_Insert_tab.count);
-- FORALL j IN INDICES OF GP_Insert_tab
FORALL j in GP_Insert_tab.first..GP_Insert_tab.last --works too
Insert into skuhist --scpomgr.skuhist
values(GP_Insert_tab(j).f1
/*GP_Insert_tab(i).startdate
,1
,10080
,GP_Insert_tab(i).qty
,GP_Insert_tab(i).item
,GP_Insert_tab(i).loc*/
);
End Loop;
Exit when c_driver%NOTFOUND; --it should be at end of the loop.
End Loop;
Close C_DRIVER;
END;
/
Hope it will help you

PL/SQL Remove Characters While Loop

Im working on an assignment, the goal being to write a procedure that has 2 inputs a string and a char and remove the char from the string.
Example: RemoveAll(123-456-789, '-') will output: 123456789.
create or replace procedure MyRemoveAll
(p_text varchar2, p_char_1 char) as
v_temp varchar2(100);
BEGIN
v_temp := p_text;
WHILE instr(v_temp, p_char_1) != 0 LOOP
v_temp := substr(v_temp, 1, instr(v_temp, p_char_1)-1)
|| substr(p_text, instr(v_temp, p_char_1)+1);
END LOOP;
dbms_output.put_line (v_temp);
END;
/
exec MyRemoveAll('123456789', '*');
exec MyRemoveAll('123-456789', '-');
exec MyRemoveAll('123*456*789', '*');
I don't get any errors when the procedure is created, and the first two executions work correctly. I've tried just running:
dbms_output.put_line (instr(123*456*789, *));
Which gave me an output of 4. So it should register for the condition of the while loop, but SQL Plus just stops at the loop. (Like it's doing an infinite loop, but it isn't).
Anyone have any ideas?
I think you need to replace p_text with v_temp in your second substr call. That way each time you loop through you are working with the updated v_temp and not the original p_text.
Here is what it would look like:
create or replace procedure MyRemoveAll
(p_text varchar2, p_char_1 char) as
v_temp varchar2(100);
BEGIN
v_temp := p_text;
WHILE instr(v_temp, p_char_1) != 0 LOOP
v_temp := substr(v_temp, 1, instr(v_temp, p_char_1)-1)
|| substr(v_temp, instr(v_temp, p_char_1)+1);
END LOOP;
dbms_output.put_line (v_temp);
END;
/
All three of your examples work with this code.
Bobby

Separating multiple rows of a select query using delimiter (Oracle)

I have a query
SELECT originating_timestamp
FROM sys.x$dbgalertext
WHERE message_text LIKE '%Starting up%'
and to_char(ORIGINATING_TIMESTAMP,'DD-MON-YY') = to_char(systimestamp,'DD-MON-YY');
The output in a linux script is as below:
09-OCT-17 04.59.33.758 AM -05:00 09-OCT-17 05.03.22.645 AM -05:00
there are two rows above each starting by date.
I would like to have the output like
09-OCT-17 04.59.33.758 AM -05:00;09-OCT-17 05.03.22.645 AM -05:00
This is just two rows, there can be many more, I would like it so that every row is separated via delimiter.
I have tried few options like
1) using listagg:
select listagg(originating_timestamp,', ') within group(order by originating_timestamp) csv
from sys.x$dbgalertext
WHERE message_text LIKE '%Starting up%'
and to_char(ORIGINATING_TIMESTAMP,'DD-MON-YY') = to_char(systimestamp,'DD-MON-YY');
But this gives error:
ERROR at line 1:
ORA-01489: result of string concatenation is too long
2) using XMLAGG:
SELECT RTRIM(XMLAGG(XMLELEMENT(E,originating_timestamp,';').EXTRACT('//text()') ORDER BY originating_timestamp).GetClobVal(),',') AS LIST
FROM sys.x$dbgalertext
WHERE message_text LIKE '%Starting up%'
and to_char(ORIGINATING_TIMESTAMP,'DD-MON-YY')= to_char(systimestamp,'DD-MON-YY');
But the output is like :
2017-10-09T04:59:33.758-05:00;2017-10-09T05:03:22.645-05:00;
Which is also not correct.
e.g. Select username from dba_users. Suppose there are 10 users, i want those 10 usernames to be separated via delimiter.
Below two anonymous block example which may be helpful to solve your problem :
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
res VARCHAR2(100);
tmp VARCHAR2(100);
BEGIN
FOR i IN 1..10 LOOP
IF i != 10 THEN
select 'a' ||',' into tmp from dual;
ELSE
select 'a' into tmp from dual;
END IF;
res := concat(res,tmp);
END LOOP;
DBMS_OUTPUT.PUT_LINE(res);
END;
/
Second :
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
res VARCHAR2(1000);
tmp VARCHAR2(1000);
BEGIN
FOR i IN 1..10 LOOP
IF i != 10 THEN
select TO_CHAR(sysdate,'DD-MON-YYYYHH24:MI') || ',' into tmp from dual;
ELSE
select TO_CHAR(sysdate,'DD-MON-YYYYHH24:MI') into tmp from dual;
END IF;
res := concat(res,tmp);
END LOOP;
DBMS_OUTPUT.PUT_LINE(res);
END;
/
You should replace my query select with yours and of course the format of date you wanna get and replace comma with your desire character .
To make it working properly i wanna suggest you to create a cursor :
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
res VARCHAR2(100);
tmp VARCHAR2(100);
cont NUMBER;
CURSOR C_1 IS
SELECT to_char(originating_timestamp,'your date format')
originating_timestamp
FROM sys.x$dbgalertext
WHERE message_text LIKE '%Starting up%'
and to_char(ORIGINATING_TIMESTAMP,'DD-MON-YY') = to_char(systimestamp,'DD-MON-YY');
BEGIN
cont := 0;
FOR C_row IN C_1 LOOP
IF cont != C_1%rowcount THEN
tmp := C_row.originating_timestamp ||',';
res := concat(res,tmp);
ELSE
tmp := C_row.originating_timestamp;
res := concat(res,tmp);
END IF;
cont := cont +1;
END LOOP;
DBMS_OUTPUT.PUT_LINE(res);
END;
/

Passsing two VARRAYS to a Procedure to pass them to a Index-By table

I try to pass two VARRAYs into a Procedure but when call it to test it I don't get any kind of respond from my database.
CREATE OR REPLACE PACKAGE PKG_TEST AS
TYPE PNO IS VARRAY(20) OF VARCHAR(20);
TYPE QTY IS VARRAY(20) OF INTEGER;
TYPE indexTest IS TABLE OF NUMBER INDEX BY VARCHAR2(20);
PROCEDURE blatest(i_PNO IN PNO, i_QTY IN QTY);
END PKG_TEST;
/
CREATE OR REPLACE PACKAGE BODY PKG_TEST AS
PROCEDURE blatest(i_PNO IN PNO , i_QTY IN QTY)
IS
V_COUNT_PNO INTEGER;
V_COUNT_QTY INTEGER;
bla_list indexTest;
name VARCHAR(20);
BEGIN
V_COUNT_PNO := i_PNO.COUNT;
V_COUNT_QTY := i_QTY.COUNT;
IF V_COUNT_PNO = V_COUNT_QTY THEN
FOR I IN 1..V_COUNT_PNO LOOP
bla_list(i_PNO(I)) := i_QTY(I);
END LOOP;
name := bla_list.FIRST;
WHILE name IS NOT null LOOP
dbms_output.put_line('Name: ' || name || ' is ' || TO_CHAR(bla_list(name)));
name := bla_list.NEXT(name);
END LOOP;
ELSE
dbms_output.put_line('Amount of Variables is not identical!');
END IF;
END blatest;
END PKG_TEST;
/
PKG_TEST.blatest(PKG_TEST.PNO('P123','P124'), PKG_TEST.QTY(2,3));
/
And if there is any easier way to fill in a Index-By table I dynamicly I am more than happy to read this ^^. Thanks in advance!
Call it as below, then you will get response:
set serveroutput on;
BEGIN
pkg_test.blatest (pkg_test.pno ('P123', 'P124'), pkg_test.qty (2, 3));
END;

PLS-00103: Encountered the symbol "&" when expecting one of the following: ( - + case mode new not null

declare
v_empno empdab.eno%type:=&n;
v_empdab empdab%rowtype;
begin
select eno, ename,doj,position,salary,comm,address into v_empdab from empdab where eno=v_empno;
dbms_output.put_line(v_empdab.eno||v_empdab.ename||v_empdab.doj||v_empdab.position||v_empdab.salary||v_empdab.comm||v_empdab.address);
end ;
SQL*Plus named parameters can be used in PL/SQL. I think you have not send us the real code.
Script start cc.sql
accept n prompt 'Enter value for n :'
set serveroutput on
declare
v_v test.v%type := &n;
r_v test%rowtype;
begin
dbms_output.put_line(v_v);
select v into v_v from test where rownum = 1;
dbms_output.put_line(v_v);
dbms_output.put_line(&n);
end;
/
End Script cc.sql
   
SQL> #cc
Enter value for n :'abc'
old 2: v_v test.v%type := &n;
new 2: v_v test.v%type := 'abc';
old 9: dbms_output.put_line(&n);
new 9: dbms_output.put_line('abc');
abc
a
abc
PL/SQL procedure successfully completed.
SQL>

Resources