How To solve this pl sql oracle query? - plsql

Write a PL/SQL program using While Loop to display all DEPTNO,DNAME and LOC
from DEPT table. Assuming the difference between two deptno is 10.
I am beginer and i am very confuse to solve this query please help to solve this problem.

Something like this?
SQL> set serveroutput on
SQL> declare
2 i dept.deptno%type; -- loop counter
3 l_max_deptno dept.deptno%type; -- upper limit
4 l_dept_row dept%rowtype; -- will contain the whole DEPT table row
5 begin
6 -- MIN -> i (which will be the starting point); MAX -> l_max_deptno (which will be the end)
7 select min(deptno), max(deptno)
8 into i, l_max_deptno
9 from dept;
10
11 while i <= l_max_deptno
12 loop
13 -- select the whole row into L_DEPT_ROW
14 select *
15 into l_dept_row
16 from dept
17 where deptno = i;
18
19 dbms_output.put_line(l_dept_row.deptno ||' - '||
20 l_dept_row.dname ||' - '||
21 l_dept_row.loc);
22 -- increment counter by 10 (because, as you said, the difference is 10)
23 i := i + 10;
24 end loop;
25 end;
26 /
10 - ACCOUNTING - NEW YORK
20 - RESEARCH - DALLAS
30 - SALES - CHICAGO
40 - OPERATIONS - BOSTON
PL/SQL procedure successfully completed.
SQL>

Here is how you do what you asked for, but bear in mind this is not the optimum way to do it. if your target is to train your self on the While loop in PLSQL, then here you go.
DECLARE
CURSOR C_DEPTS
IS
SELECT DEPTNO, DNAME, LOC FROM DEPT;
V_DEPTNO VARCHAR2 (255);
V_DNAME VARCHAR2 (255);
V_LOC VARCHAR2 (255);
BEGIN
OPEN C_DEPTS;
FETCH C_DEPTS INTO V_DEPTNO, V_DNAME, V_LOC;
WHILE C_DEPTS%FOUND
LOOP
DBMS_OUTPUT.PUT_LINE ('DEPTNO = ' || V_DEPTNO);
DBMS_OUTPUT.PUT_LINE ('DNAME = ' || V_DNAME);
DBMS_OUTPUT.PUT_LINE ('LOC = ' || V_LOC);
FETCH C_DEPTS INTO V_DEPTNO, V_DNAME, V_LOC;
END LOOP;
END;

Related

how to create index by using dynamic sql?

----------- it is giving below error ,where i did mistake ---------------
declare l1 integer;
begin execute immediate q '!
begin
execute immediate ' CREATE INDEX S_ACCNT_ATT_P1 ON S_ACCNT_ATT(ROW_ID) PARALLEL 4 ';
execute immediate ' CREATE INDEX S_ACCNT_ATT_U1 ON S_ACCNT_ATT(PAR_ROW_ID, FILE_NAME, FILE_EXT, CONFLICT_ID) PARALLEL 4 ';
execute immediate '
select 1 from dual '
into :l1;
end;!' using out l1;
end;
------- error -------------------
ORA-06550: line 2, column 27:
PLS-00103: Encountered the symbol "!
begin
execute immediate " when expecting one of the following:
The issue is the incorrect q-quoting syntax. That is causing the error you're seeing.
DECLARE
BEGIN
EXECUTE IMMEDIATE q '!BEGIN NULL; END;!';
END;
/
Error report -
ORA-06550: line 3, column 23:
PLS-00103: Encountered the symbol "!BEGIN NULL; END;!" when expecting one of the following:
. ( * # % & = - + ; < / > at in is mod remainder not rem
return returning <an exponent (**)> <> or != or ~= >= <= <>
and or like like2 like4 likec between into using || multiset
bulk member submultiset
The symbol "*" was substituted for "!BEGIN NULL; END;!" to continue.
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
There should be no space between the q and the ':
DECLARE
BEGIN
EXECUTE IMMEDIATE q'!BEGIN NULL; END;!';
END;
/
PL/SQL procedure successfully completed.
How/where exactly did you run that piece of code? I tested it on TOAD and SQL*Plus in Oracle 11g.
Sample table:
SQL> CREATE TABLE s_accnt_att
2 (
3 row_id NUMBER,
4 par_row_id NUMBER,
5 file_name NUMBER,
6 file_ext NUMBER,
7 conflict_id NUMBER
8 );
Table created.
Procedure:
SQL> SET SERVEROUTPUT ON;
SQL>
SQL> DECLARE
2 l1 INTEGER;
3 BEGIN
4 EXECUTE IMMEDIATE q'[
5 begin
6 execute immediate ' CREATE INDEX S_ACCNT_ATT_P1 ON S_ACCNT_ATT ( ROW_ID ) PARALLEL 4 ';
7 execute immediate ' CREATE INDEX S_ACCNT_ATT_U1 ON S_ACCNT_ATT ( PAR_ROW_ID , FILE_NAME , FILE_EXT , CONFLICT_ID ) PARALLEL 4 ';
8 execute immediate ' select 1 from dual '
9 into :l1;
10 end;
11 ]'
12 USING OUT l1;
13
14 DBMS_OUTPUT.put_line ('L1 = ' || l1);
15 END;
16 /
L1 = 1
PL/SQL procedure successfully completed.
SQL>
Seems to be OK.
As your target database is 19c, I tried it there as well; no problem.
SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
SQL> DECLARE
2 l1 INTEGER;
3 BEGIN
4 EXECUTE IMMEDIATE q'[
5 begin
6 execute immediate ' CREATE INDEX S_ACCNT_ATT_P1 ON S_ACCNT_ATT ( ROW_ID ) PARALLEL 4 ';
7 execute immediate ' CREATE INDEX S_ACCNT_ATT_U1 ON S_ACCNT_ATT ( PAR_ROW_ID , FILE_NAME , FILE_EXT , CONFLICT_ID ) PARALLEL 4 ';
8 execute immediate ' select 1 from dual '
9 into :l1;
10 end;
11 ]'
12 USING OUT l1;
13
14 DBMS_OUTPUT.put_line ('L1 = ' || l1);
15 END;
16 /
L1 = 1
PL/SQL procedure successfully completed.
SQL>
Therefore, maybe it is about your migration tool (which one is it) that doesn't recognize the q-quoting mechanism. If that's so, don't use it and double single quotes instead:
SQL> DECLARE
2 l1 INTEGER;
3 BEGIN
4 EXECUTE IMMEDIATE '
5 begin
6 execute immediate '' CREATE INDEX S_ACCNT_ATT_P1 ON S_ACCNT_ATT ( ROW_ID ) PARALLEL 4 '';
7 execute immediate '' CREATE INDEX S_ACCNT_ATT_U1 ON S_ACCNT_ATT ( PAR_ROW_ID , FILE_NAME , FILE_EXT , CONFLICT_ID ) PARALLEL 4 '';
8 execute immediate '' select 1 from dual ''
9 into :l1;
10 end;
11 '
12 USING OUT l1;
13
14 DBMS_OUTPUT.put_line ('L1 = ' || l1);
15 END;
16 /
PL/SQL procedure successfully completed.
SQL>

PLS-00201 Error in Pipelined Function in PL/SQL

I was trying to create a pipelined table function in PL/SQL but facing the below error. Is this an syntax error?
CREATE OR REPLACE FUNCTION FUNC_IDS(
IDS_IN IN VARCHAR2
) RETURN IDS_T
PIPELINED
IS
BEGIN
select * from dual;
return;
END func_ids;
Script Output:
Function FUNC_IDS compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
3/10 PLS-00201: identifier 'IDS_T' must be declared
Errors: check compiler log
I missed to create the row and table types before creating the func. Have created them later as below and trying to create the function that gets input as a string of IDs and pipe out the individual IDs to another function.
CREATE TYPE TF_ROW AS OBJECT (ID NUMBER);
CREATE TYPE IDS_T IS TABLE OF TF_ROW;
create or replace function func_ids (ids_in in varchar2) return ids_t pipelined is
n_start pls_integer := 1;
n_end pls_integer := 1;
--
begin
loop
-- find the first and next comma in string
n_start := instr(ids_in, ',', n_start, 1);
n_end := instr(ids_in, ',', n_start, 2);
--
if (n_end <= 0) then
exit;
end if;
-- get the string and pipe it back out
pipe row (to_number(substr(ids_in, n_start+1, n_end - n_start - 1)));
-- ready for next one
n_start := n_end;
end loop;
return;
end func_ids;
Script Output:
Function FUNC_IDS compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
22/5 PL/SQL: Statement ignored
22/15 PLS-00382: expression is of wrong type
Errors: check compiler log
What's wrong with the expression here?pipe row (to_number(substr(ids_in, n_start+1, n_end - n_start - 1)));
As you were told, IDS_T isn't declared.
Here's an example which works. See how I did it, do it yourself with your data.
Types:
SQL> create or replace type t_row is object (empno number, ename varchar2 (20));
2 /
Type created.
SQL> create or replace type t_tab is table of t_row;
2 /
Type created.
Function:
SQL> create or replace function func_ids (ids_in in varchar2)
2 return t_tab
3 pipelined
4 is
5 begin
6 for cur_r in (select empno, ename
7 from emp
8 where deptno = ids_in)
9 loop
10 pipe row (t_row (cur_r.empno, cur_r.ename));
11 end loop;
12
13 return;
14 end func_ids;
15 /
Function created.
Testing:
SQL> select * from table(func_ids (20));
EMPNO ENAME
---------- --------------------
7369 SMITH
7566 JONES
7788 SCOTT
7876 ADAMS
7902 FORD
SQL>
How to use the result returned by FUNC_IDS? I'm doing it using code you posted as a comment (the FUNC_ENAME function); I marked what you did wrong.
SQL> CREATE OR REPLACE FUNCTION func_ename (ids t_tab)
2 RETURN VARCHAR2
3 IS
4 l_tmp VARCHAR2 (100);
5 l_result VARCHAR2 (400);
6 BEGIN
7 l_result := ';';
8
9 FOR i IN ids.FIRST .. ids.LAST
10 LOOP
11 SELECT l.ename
12 INTO l_tmp
13 FROM emp l
14 WHERE l.empno = ids (i).empno; --> this line was wrong
15
16 l_result := l_result || l_tmp || ';';
17 END LOOP;
18
19 RETURN l_result;
20 END;
21 /
Function created.
SQL> SELECT func_ename (func_ids (10)) FROM DUAL;
FUNC_ENAME(FUNC_IDS(10))
------------------------------------------------------------------
;CLARK;KING;MILLER;
SQL>

Use cursor in LOOP in new QUERY

"I missing the forest through the trees..."
I want to query each column of a table which I retrieve in a FOR LOOP, but the inner query doesn't return the right thing.
Seems that the inner query not use the current column_name.
DECLARE
v_max_TS TIMESTAMP;
BEGIN
FOR cols IN (SELECT column_name FROM all_tab_cols WHERE table_name = '<tablename>')
LOOP
SELECT
MAX(CURR_TIMESTAMP) INTO v_max_TS
FROM <tablename>
WHERE cols.column_name IS NOT NULL
ORDER BY TO_TIMESTAMP(CURR_TIMESTAMP,'MM/DD/YYYY HH24:MI:SS') DESC;
dbms_output.put_line(cols.column_name || ' ' || v_max_TS);
END LOOP;
END;
Apart from the fact that your query doesn't make much sense (as Boneist wrote as a comment), that won't work as you need to use dynamic SQL (execute immediate) for such a purpose.
Here's an example based on Scott's schema. Have a look, adjust it if necessary.
SQL> set serveroutput on
SQL> declare
2 l_str varchar2(200); -- will hold the SELECT statement
3 v_max varchar2(30);
4 begin
5 for cols in (select column_name
6 from all_tab_cols
7 where table_name = 'DEPT'
8 )
9 loop
10 l_str := 'select max(' || cols.column_name ||') from dept';
11 execute immediate l_str into v_max;
12 dbms_output.put_line(cols.column_name ||': '|| v_max);
13 end loop;
14 end;
15 /
DEPTNO: 40
DNAME: SALES
LOC: NEW YORK
PL/SQL procedure successfully completed.
SQL>

LISTAGG IN PL/SQL

Help please find mistake in creating function which will return one row from list.
SELECT listagg(' ' || V_RECEIVING_LIST.DOCUMENT_NUMBER || CHR(13))
WITHIN GROUP (ORDER BY V_RECEIVING_LIST.DOCUMENT_NUMBER)
FROM svc.claim_detail, tbc.v_receiving_list
WHERE claim_detail.id_claim = 334455
AND V_RECEIVING_LIST.ID_RECEIVING_LIST = CLAIM_DETAIL.ID_RECEIVING_LIST
The code return correct result.
But the next dont return the same.
DECLARE
scodes VARCHAR2 (4000);
BEGIN
SELECT (LISTAGG(' ' || RECEIVING_LIST.DOCUMENT_NUMBER || CHR(13))
WITHIN GROUP (ORDER BY RECEIVING_LIST.DOCUMENT_NUMBER))
INTO scodes
FROM svc.claim_detail, tbc.v_receiving_list
WHERE claim_detail.id_claim = 334455
AND RECEIVING_LIST.ID_RECEIVING_LIST = CLAIM_DETAIL.ID_RECEIVING_LIST;
DBMS_OUTPUT.PUT_LINE(scodes);
END;
SQL> select * from V_RECEIVING_LIST ;
DOCUMENT_NUMBER ID_RECEIVING_LIST
--------------- --------------------
1 a
1 a
2 b
SQL> select * from claim_detail ;
ID_CLAIM ID_RECEIVING_LIST
---------- --------------------
123 a
123 a
124 b
SQL> DECLARE
2 scodes VARCHAR2 (4000);
3 BEGIN
4 SELECT (LISTAGG(' '|| v_receiving_list.DOCUMENT_NUMBER || CHR(13))
5 WITHIN GROUP (ORDER BY v_receiving_list.DOCUMENT_NUMBER))
6
7 INTO scodes
8 FROM claim_detail, v_receiving_list
9 WHERE claim_detail.id_claim = 123
10 AND v_receiving_list.ID_RECEIVING_LIST = CLAIM_DETAIL.ID_RECEIVING_LIST;
11
12
13 DBMS_OUTPUT.PUT_LINE('The output is '||scodes);
14 END;
15 /
1e output is 1
PL/SQL procedure successfully completed.

How to setup dbms_job with out parameter

I'm trying to run some procedures in parallel using dbms_jobs but i'm having some issues doing it. When trying to run below code, i'm getting this error
20:28:16 Info: Job #16 could not be executed. ORA-12011: execution of 1 jobs failed
ORA-06512: at "SYS.DBMS_IJOB", line 469
ORA-06512: at "SYS.DBMS_JOB", line 282
ORA-06512: at line 1
declare
ln_dummy number;
p_stdate CONSTANT DATE := '01-MAY-2012';
p_edate CONSTANT DATE := '31-MAY-2012';
p_cdate CONSTANT DATE := '09-FEB-2013';
p_key CONSTANT INTEGER:= 0;
p_ercode INTEGER;
p_erdesc VARCHAR2(200);
begin
COMMIT;
DBMS_JOB.SUBMIT(ln_dummy,'MY_PROC_1('''|| p_stdate ||''','''|| p_edate ||''','''|| p_cdate||''','''|| p_key ||''', :p_ercode, :p_erdesc: );');
COMMIT;
end;
/
p_ercode and p_erdesc is an out parameter in MY_PROC_1. If I try to comment it out the job runs without an issue.
My question is how can I run the job without commenting out p_ercode and p_erdesc in MY_PROC_1.
Also, is there a way to know which job is running and which job is already done? Something like an alert?
Maybe, this will work?
declare
ln_dummy number;
p_stdate CONSTANT DATE := '01-MAY-2012';
p_edate CONSTANT DATE := '31-MAY-2012';
p_cdate CONSTANT DATE := '09-FEB-2013';
p_key CONSTANT INTEGER:= 0;
begin
COMMIT;
DBMS_JOB.SUBMIT(ln_dummy,'
declare
p_ercode INTEGER;
p_erdesc VARCHAR2(200);
begin
MY_PROC_1('''|| p_stdate ||''','''|| p_edate ||''','''|| p_cdate||''','''|| p_key ||''', p_ercode, p_erdesc );
end;
');
COMMIT;
end;
if you want to log the outputs you can create a table:
SQL> create table log_table
2 (
3 job_id number,
4 start_time date,
5 end_time date,
6 retcode number,
7 retstr varchar2(4000)
8 )
9 /
Table created.
then execute the job. i've made a wrapper procedure just to make it a bit neater but you could put all of this in the job if you wanted.
SQL> create or replace procedure my_proc_1_job(
2 p_job number,
3 p_stdate date,
4 p_edate date,
5 p_cdate date,
6 p_key integer)
7 is
8 v_errcode integer;
9 v_errdesc varchar2(32767);
10 v_start_date date;
11 begin
12 v_start_date := sysdate;
13 my_proc_1(p_stdate, p_edate, p_cdate, p_key, v_errcode, v_errdesc);
14 insert into log_table (job_id, start_time, end_time, retcode, retstr)
15 values (p_job, v_start_date, sysdate, v_errcode, v_errdesc);
16 commit;
17 end;
18 /
Procedure created.
SQL> declare
2 ln_dummy number;
3 p_stdate CONSTANT varchar2(20) := '01-MAY-2012';
4 p_edate CONSTANT varchar2(20) := '31-MAY-2012';
5 p_cdate CONSTANT varchar2(20) := '09-FEB-2013';
6 p_key CONSTANT INTEGER:= 0;
7 begin
8 COMMIT;
9 DBMS_JOB.SUBMIT(
10 ln_dummy,
11 'my_proc_1_job(
12 JOB, to_date('''|| p_stdate ||''',''DD-MON-YYYY''),
13 to_date('''|| p_edate ||''',''DD-MON-YYYY''),
14 to_date('''|| p_cdate ||''',''DD-MON-YYYY''),
15 ' || p_key || ');');
16 COMMIT;
17 end;
18 /
PL/SQL procedure successfully completed.
SQL> select * from log_table;
JOB_ID START_TIM END_TIME RETCODE
---------- --------- --------- ----------
RETSTR
----------------------------------------------------------------------------------------------------
4 10-FEB-13 10-FEB-13 -1
failure
now all runs are recorded in LOG_TABLE.

Resources