Too many values inside a Where - sql

I want to get all products inside an order. I give to my procedure the ID of the order and then I want to list all of them.
Here is the database scheme of the tables I use in this procedure:
And here is the procedure:
CREATE OR REPLACE PROCEDURE exercitiu6(v_ID_Comanda Comanda.ID_Comanda%TYPE) AS
TYPE produse IS TABLE OF Produs%ROWTYPE INDEX BY PLS_INTEGER;
p produse;
TYPE imbricat IS TABLE OF ProduseComanda.ID_Produs%TYPE;
imbricat_produse imbricat:= imbricat();
prod Produs%ROWTYPE;
i number:=0;
j number:=0;
BEGIN
SELECT ID_Produs BULK COLLECT INTO imbricat_produse FROM ProduseComanda
WHERE ID_Comanda = v_ID_Comanda;
FOR i IN imbricat_produse.FIRST..imbricat_produse.LAST LOOP
SELECT ID_Produs, nume, pret INTO prod FROM Produs
WHERE ID_Produs = imbricat_produse(i);
p(j):= prod;
j:= j + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Comanda cu ID-ul ' || v_ID_Comanda || ' contine urmatoarele produse: ');
FOR j IN p.FIRST..p.LAST LOOP
DBMS_OUTPUT.PUT_LINE(p(j).nume);
END LOOP;
END;
I get the Error Sql Statement ignored; too many values on this line:
WHERE ID_Comanda = v_ID_Comanda;
How do I solve this error?

Use a JOIN and a single cursor:
CREATE OR REPLACE PROCEDURE exercitiu6(
v_ID_Comanda ProduseComanda.ID_Comanda%TYPE
)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Comanda cu ID-ul ' || v_ID_Comanda || ' contine urmatoarele produse: ');
FOR i IN (
SELECT p.nume
FROM ProduseComanda c
INNER JOIN Produs p
ON p.ID_Produs = c.ID_Produs
WHERE c.ID_Comanda = v_ID_Comanda
)
LOOP
DBMS_OUTPUT.PUT_LINE(i.nume);
END LOOP;
END;
/
Then, for the sample data:
CREATE TABLE produsecomanda (ID_Produs, ID_Comanda) AS
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 2, 1 FROM DUAL UNION ALL
SELECT 3, 1 FROM DUAL;
CREATE TABLE produs (ID_Produs, nume) AS
SELECT 1, 'Alice' FROM DUAL UNION ALL
SELECT 2, 'Beryl' FROM DUAL UNION ALL
SELECT 3, 'Carol' FROM DUAL;
Then:
BEGIN
DBMS_OUTPUT.ENABLE();
exercitiu6(1);
END;
/
Outputs:
Comanda cu ID-ul 1 contine urmatoarele produse:
Alice
Beryl
Carol
If you want to fix your code then the error is not with the WHERE clause but with the mismatch between the number of columns in the SELECT clause and the INTO clause. To fix it you need to use SELECT * INTO ... rather than naming all the columns when you are working with %ROWTYPE variables:
CREATE OR REPLACE PROCEDURE exercitiu6(
v_ID_Comanda ProduseComanda.ID_Comanda%TYPE
)
AS
TYPE produse IS TABLE OF Produs%ROWTYPE INDEX BY PLS_INTEGER;
p produse;
TYPE imbricat IS TABLE OF ProduseComanda.ID_Produs%TYPE;
imbricat_produse imbricat;
i number:=0;
j number:=0;
BEGIN
SELECT ID_Produs
BULK COLLECT INTO imbricat_produse
FROM ProduseComanda
WHERE ID_Comanda = v_ID_Comanda;
FOR i IN imbricat_produse.FIRST..imbricat_produse.LAST LOOP
j:= j + 1;
SELECT *
INTO p(j)
FROM Produs
WHERE ID_Produs = imbricat_produse(i);
END LOOP;
DBMS_OUTPUT.PUT_LINE('Comanda cu ID-ul ' || v_ID_Comanda || ' contine urmatoarele produse: ');
FOR j IN p.FIRST..p.LAST LOOP
DBMS_OUTPUT.PUT_LINE(p(j).nume);
END LOOP;
END;
/
fiddle

Related

pl/sql multiple if or multiple begin when data found block

I am new to writing stored procedures. I want to see which is the best way to execute a functionality like below:
cursor c1 is select * from cases where caseid = '2332534534';
begin
for t_case in c1
loop
/..///
if t_case.oCode is not null then
select id into v_ao from lkp_ao where upper(descr) = upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode));
if v_ao = 0 then
select id into v_ao from lkp_ao where substr(upper(descr),1,5) like substr(upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode)),1,5)||'%' and rownum=1;
if v_ao = 0 then
select id into v_ao from lkp_ao where substr(upper(descr),1,5) like substr(upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode)),1,4)||'%' and rownum=1;
if v_ao = 0 then
select id into v_ao from lkp_ao where substr(upper(descr),1,5) like substr(upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode)),1,3)||'%' and rownum=1;
if v_ao = 0 then
v_ao := '';
end if;
end if;
end if;
end if;
else
v_ao := '';
end if;
/..///
end loop;
commit;
exception
when others then
log_error(0, 'INSERT_case - exception outside' || SQLERRM || ' code ' || SQLCODE, 1);
commit;
end;
This part of code would not work. so instead of select id into v_ao , i will have to check
select count(*) into v_ao from lkp_ao where upper(descr) = upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode));
if v_ao = 0 then
//do something
else
select id into v_ao from lkp_ao where upper(descr) = upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode));
end if;
So i am executing 1 query for count and 1 query to get the actual id in the else part.
The other way of doing is using begin when no data found execute the 2nd query and inside that no data found open another begin and so on. So basically there will be 5 begin and exception when no data found block which i feel is huge code.
Whats the simplest way to do this kind of condition in oracle stored procedure? thanks in advance.
Get all the matching rows in a single statement (so you do not have to query the table multiple times) and then use a CASE statement to order the rows and only get the best match:
DECLARE
v_substr CASES.OCODE%TYPE;
cursor c1 is select * from cases where caseid = '2332534534';
BEGIN
for t_case in c1
loop
/* ... */
if t_case.oCode is not null then
IF instr(t_case.oCode,',') = 0 THEN
v_substr := UPPER(t_case.oCode);
ELSE
v_substr := UPPER(SUBSTR(t_case.oCode, 1, INSTR(t_case.oCode,',')-1));
END IF;
v_ao := ''; -- same as NULL
BEGIN
SELECT id
INTO v_ao
from lkp_ao
WHERE substr(upper(descr),1,3) = SUBSTR(v_substr, 1, 3)
ORDER BY
CASE
WHEN upper(descr) = v_substr
THEN 1
WHEN substr(upper(descr),1,5) = SUBSTR(v_substr, 1, 5)
THEN 2
WHEN substr(upper(descr),1,4) = SUBSTR(v_substr, 1, 4)
THEN 3
WHEN substr(upper(descr),1,3) = SUBSTR(v_substr, 1, 3)
THEN 4
END
FETCH FIRST ROW ONLY;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END IF;
/* .. */
end loop;
commit;
exception
when others then
log_error(0, 'INSERT_case - exception outside' || SQLERRM || ' code ' || SQLCODE, 1);
commit; -- Really commit after an exception?
END;
/
If you want to make it even more efficient then do all the matching in the cursor query (then you do not have to context switch in every iteration of the cursor between PL/SQL and SQL):
DECLARE
v_substr CASES.OCODE%TYPE;
CURSOR c1 IS
SELECT c.*,
l.id AS ao
FROM (
SELECT c.*,
CASE INSTR(oCode, ',')
WHEN 0 THEN oCode
ELSE SUBSTR(oCode, 1, INSTR(oCode, ',') - 1)
END AS term
FROM cases c
) c
LEFT OUTER JOIN LATERAL (
SELECT id
from lkp_ao a
WHERE substr(upper(a.descr),1,3) = SUBSTR(c.term, 1, 3)
ORDER BY
CASE
WHEN upper(a.descr) = c.term
THEN 1
WHEN substr(upper(a.descr),1,5) = SUBSTR(c.term, 1, 5)
THEN 2
WHEN substr(upper(a.descr),1,4) = SUBSTR(c.term, 1, 4)
THEN 3
WHEN substr(upper(a.descr),1,3) = SUBSTR(c.term, 1, 3)
THEN 4
END
FETCH FIRST ROW ONLY
) l
ON (1 = 1)
WHERE caseid = '2332534534';
BEGIN
for t_case in c1
loop
/* ... */
v_ao := t_case.ao;
/* .. */
end loop;
commit;
exception
when others then
log_error(0, 'INSERT_case - exception outside' || SQLERRM || ' code ' || SQLCODE, 1);
commit; -- Really commit after an exception?
END;
/
Well,
if you declare additional variables and run all select statements (each of them returning its own v_ao# value) and
apply the max function so that query wouldn't end up with NO_DATA_FOUND; it'll return NULL instead
SQL> select 1 from dual where 1 = 2;
no rows selected
SQL> select max(1) From dual where 1 = 2;
MAX(1)
----------
SQL>
then you wouldn't have to enclose each select into its own begin-exception-end block
use nested CASE expressions to return the final result
Something like this:
declare
v_ao1 number;
v_ao2 number;
v_ao3 number;
v_ao4 number;
v_ao number;
begin
for t_case in c1 loop
select max(id) into v_ao1 from lkp_ao where upper(descr) = upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode));
select max(id) into v_ao2 from lkp_ao where substr(upper(descr),1,5) like substr(upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode)),1,5)||'%' and rownum=1;
select max(id) into v_ao3 from lkp_ao where substr(upper(descr),1,5) like substr(upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode)),1,4)||'%' and rownum=1;
select max(id) into v_ao4 from lkp_ao where substr(upper(descr),1,5) like substr(upper(nvl(substr(t_case.oCode, 1, instr(t_case.oCode,',')-1), t_case.oCode)),1,3)||'%' and rownum=1;
v_ao := case when nvl(v_ao1, 0) = 0 then
case when nvl(v_ao2, 0) = 0 then
case when nvl(v_ao3, 0) = 0 then
case when nvl(v_ao4, 0) = 0 then null
else v_ao4
end
else v_ao3
end
else v_ao2
end
else v_ao1
end;
end loop;
end;
Sometimes, in such cases, it's better to get length of longest match. One of the variants for this is to use UTL_RAW.BIT_XOR:
with
t(s) as (
select 'AAAABB' from dual union all
select 'AAAABC' from dual union all
select 'AAABBC' from dual union all
select 'BBBXXXX' from dual union all
select 'BBBYYY' from dual
)
,search_strings(str) as (
select 'AAAAB' from dual union all
select 'BBBZZZ' from dual
)
select
t.s,s.str,
utl_raw.bit_xor(utl_raw.cast_to_raw(t.s),utl_raw.cast_to_raw(s.str)) s_xor,
length(
regexp_substr(
utl_raw.bit_xor(utl_raw.cast_to_raw(t.s),utl_raw.cast_to_raw(s.str))
,'^(00)+'
)
)/2 as n_matches
from t, search_strings s
;
Results:
S STR S_XOR N_MATCHES
------- ------ ------------------------------ ----------
AAAABB AAAAB 000000000042 5
AAAABC AAAAB 000000000043 5
AAABBC AAAAB 000000030043 3
BBBXXXX AAAAB 030303191A5858
BBBYYY AAAAB 030303181B59
AAAABB BBBZZZ 0303031B1818
AAAABC BBBZZZ 0303031B1819
AAABBC BBBZZZ 030303181819
BBBXXXX BBBZZZ 00000002020258 3
BBBYYY BBBZZZ 000000030303 3
10 rows selected.
As you can see, BIT_XOR returns '00' for equal chars so you can count a number of 00 in it. Column n_matches returns this number of matched symbols

Error: Table or view does not exist in PL SQL package

I have a package called 'S_PKG' in schema 'A'. I want to migrate it into schema B. What I did was I copied the code and executed in B schema. Then I wanted to execute the following pl sql script in which the 'S_PKG' is used in schema B.
select to_char(sysdate,'YYYYMMDD - HH:MI:SS AM') date_time
from dual
/
insert into zzz_ccc
select zzz_ccc_seq.nextval,to_char(sysdate,'YYYYMMDD - HH:MI:SS AM'),
'Start S Load tab',8,user,(select * from global_name)
from dual
/
commit
/
insert into zzz
select zzz_seq.nextval,to_char(sysdate,'YYYYMMDD - HH:MI:SS AM'),
'Start S Load tab',
(select trim(ruser)||' '||trim(rdbase)
from zzz_ccc where ss = 8
and rr = (select max(rr) from zzz_ccc where ss = 8)),
null,null,null,null,null,null,
(select max(rr) from zzz_ccc where ss = 8)
from dual
/
commit
/
DECLARE
PV_PRD_ID VARCHAR2(5);
BEGIN
PV_PRD_ID := '3';
B.S_PKG.PR_MAIN (PV_PRD_ID);
COMMIT;
END;
/
commit
/
insert into tab_counts(created_dtm,
ora_database,ora_user,ora_table,cc,flg,
subj)
select sysdate,'ccenter','aim10_ccenter','s_package_run - rows',
no_of_rows,1,
'S Load Tab Run'
from s_package_run
where to_char(st_date,'YYYYMM-DD') = to_char(sysdate,'YYYYMM-DD')
and package_name = 'LOAD_TAB'
/
commit
/
insert into tab_counts(created_dtm,
ora_database,ora_user,ora_table,cc,flg,
subj)
select sysdate,'ccenter','aim10_ccenter','s_package_run - dur_min',
dur_min,2,
'S Load Tab Run'
from s_package_run
where to_char(st_date,'YYYYMM-DD') = to_char(sysdate,'YYYYMM-DD')
and package_name = 'LOAD_TAB'
/
insert into hrc_chk_mar14_24_1
select sysdate, 'B', 'COUNT 6 ', 's_load_tab',
null,null,null,null
from dual t1
/
insert into zzz
select zzz_seq.nextval,to_char(sysdate,'YYYYMMDD - HH:MI:SS AM'),
'End S Load tab',
(select trim(ruser)||' '||trim(rdbase)
from zzz_ccc where ss = 8
and rr = (select max(rr) from zzz_ccc where ss = 8)),
null,null,
null,null,null,null,
(select max(rr) from zzz_ccc where ss = 8)
from dual
/
commit
/
Then I got the following error.
ORA-00942: table or view does not exist
ORA-06512: at "B.S_PKG", line 109
ORA-06512: at "B.S_PKG", line 35
ORA-06512: at line 5
Then I searched for the package. But I could not find the exact table which gives me the error. Here is my package.
CREATE OR REPLACE PACKAGE BODY B.S_PKG is
PROCEDURE PR_Main(kseq number) IS
sql_stmnt varchar2(5000);
begin
select s_pkg_seq.nextval into dd from dual;
pkg_st_date := sysdate;
sql_stmnt:='truncate table s_msgs';
execute immediate sql_stmnt;
begin
for c_rec in (select * from s_test_1 where pkg_seq = kseq and
flg = 'as' order by pkg_ord)
loop
if substr(c_rec.run_sql,1,1) != '-' then
pkg_name := c_rec.run_sql;
PR_Msgs('*** '||c_rec.run_sql||' Started...', pkg_name||'.'||'pr_main');
else
PR_Msgs(c_rec.run_sql, pkg_name||'.'||'pr_main');
end if;
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
PR_LOAD_PRODUCT3(1,kseq);
PR_LOAD_PRODUCT3(2,kseq);
PR_LOAD_PRODUCT3(3,kseq);
PR_LOAD_PRODUCT3(4,kseq);
PR_LOAD_PRODUCT3(5,kseq);
PR_LOAD_PRODUCT3(6,kseq);
PR_LOAD_PRODUCT3(7,kseq);
PR_LOAD_PRODUCT3(8,kseq);
PR_LOAD_PRODUCT3(9,kseq);
PR_LOAD_PRODUCT3(10,kseq);
PR_LOAD_PRODUCT3(11,kseq);
begin
for c_rec in (select * from s_test_1 where pkg_seq = kseq and
flg = 'ae' order by pkg_ord)
loop
if substr(c_rec.run_sql,1,1) != '-' then
PR_Msgs('*** '||c_rec.run_sql||' End OK...', pkg_name||'.'||'pr_main');
else
PR_Msgs(c_rec.run_sql, pkg_name||'.'||'pr_main');
end if;
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
sql_stmnt:='insert into s_msgs_his select * from s_msgs where msg_ord > 0';
execute immediate sql_stmnt;
pkg_en_date := sysdate;
insert into s_package_run values (pkg_st_date,pkg_en_date,floor((pkg_en_date-pkg_st_date)*24*60),
(pkg_en_date-pkg_st_date)*24*60*60 - floor((pkg_en_date-pkg_st_date)*24*60)*60,gv_count,
pkg_name,null,dd);
end;
-- ==============================================================================================
-- ==============================================================================================
PROCEDURE PR_LOAD_PRODUCT3(pseq number, tseq number) is
sql_stmnt VARCHAR2(5000);
begin
prc_st_date := sysdate;
begin
for c_rec in (select * from s_test_1 where pkg_seq = tseq and
prc_seq = pseq and flg = 'bs' order by pkg_ord)
loop
prc_name := c_rec.run_sql;
PR_Msgs(c_rec.run_sql||' Started...', pkg_name||'.'||'pr_main');
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
begin
for c_rec in (select * from s_test_1 where pkg_seq = tseq and
prc_seq = pseq and flg = 'aa' order by pkg_ord)
loop
sql_stmnt := c_rec.run_sql;
execute immediate sql_stmnt;
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
begin
for c_rec in (select * from s_test_1 where pkg_seq = tseq and
prc_seq = pseq and flg = 'be' order by pkg_ord)
loop
if substr(c_rec.run_sql,1,1) != '-' then
PR_Msgs(c_rec.run_sql||' End OK...', pkg_name||'.'||'pr_main');
else
PR_Msgs(c_rec.run_sql, pkg_name||'.'||'pr_main');
end if;
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
select cc into gv_count
from cr2_test_2;
prc_en_date := sysdate;
insert into s_procedure_run values (prc_st_date,prc_en_date,floor((prc_en_date-prc_st_date)*24*60),
(prc_en_date-prc_st_date)*24*60*60 - floor((prc_en_date-prc_st_date)*24*60)*60,gv_count,
prc_name,pkg_name,dd);
end;
-- ==============================================================================================
-- ==============================================================================================
PROCEDURE PR_Msgs(pv_msg varchar2, pv_point varchar2) as
cc number(5);
Begin
select s_pkg2_seq.nextval into cc from dual;
insert into s_msgs values (sysdate, pv_msg, pv_point, user, '','',cc);
commit;
End;
-- ==============================================================================================
-- ==============================================================================================
END S_PKG;
/
Can anyone help me to find the error as I am new to PL SQL packages?
As far as I can tell, if you compiled the package when connected as user B and it was successful, then the only "unknown" information at that time is this:
sql_stmnt:='truncate table s_msgs';
i.e. the table you're truncating using dynamic SQL. sql_stmnt's value is a string, compiler doesn't check what's in there. But, when you actually execute it, then it finds out that there's no table s_msgs in user B's schema.
The same goes for
sql_stmnt:='insert into s_msgs_his select * from s_msgs where msg_ord > 0';
and table s_msgs_his.
As you moved everything from A to B, I guess that you should do the same with those tables. Do that and then try to run your code again.
[EDIT]
This is line 109:
for c_rec in (select * from s_test_1 where pkg_seq = tseq and
prc_seq = pseq and flg = 'aa' order by pkg_ord)
loop
sql_stmnt := c_rec.run_sql;
execute immediate sql_stmnt; --> line 109
Check what's written in S_TEST_1. Looks like some statement that is supposed to be executed dynamically, but - the table involved into it doesn't exist in schema B (or that user doesn't have privileges to use it).

fetch table name from a column for from clause

I have a view t with me which has a column for table name and another column which has where clause condition.
id| name|table_in| where_clause
1 | Sam | t1 | age = 22
2 | John| t2 | age = 23 and sex = 'male'
and so on...
Now, I have put the records in a cursor and I want to run each query.
create or replace procedure create_cursor
is
CURSOR v_records is
select * from t ;
begin
FOR temp IN v_records LOOP
INSERT INTO myTable (id, name)
select temp.id, temp.name
from temp.table where temp.where_clause;
END LOOP;
end;
/
myTable is another table in which I want to put the records for next purpose.
#Akshay,
Please find the code below for your reference.
Create or replace procedure create_cursor is
l_statement varchar2(32767);
cursor v_records is
select * from t;
begin
for temp in v_records
loop
l_statement := 'INSERT INTO myTable (id, name) select '||temp.id||','
||temp.name|| ' from ' || temp.table1
|| ' where ' || temp.where_clause;
execute immediate l_statement;
end loop;
end;
/
You need dynamic sql to do this:
CREATE OR REPLACE PROCEDURE create_cursor
IS
l_statement VARCHAR2(32767);
CURSOR v_records
IS
SELECT * FROM t;
BEGIN
FOR temp IN v_records
LOOP
l_statement := 'INSERT INTO myTable (id, name)
select id, name from ' || temp.table ||
' where ' || temp.where_clause;
EXECUTE immediate l_statement;
END LOOP;
END;
/

Cursor inside procedure body

I am trying to declare a cursor inside procedure body.
I know it is supposed to be done in the declare block but the table the cursor refers is created inside the procedure body.
--TABLE MAY OR MAY NOT BE PRESENT PRIOR TO PROCEDURE EXECUTION
SELECT COUNT(*)
INTO ln_cnt
FROM User_Tables
WHERE table_name = 'TMP$UOM_COMBO_GEN';
IF ln_cnt > 0 THEN
EXECUTE IMMEDIATE ' CREATE TABLE TMP$UOM_COMBO_GEN (UOM_ID VARCHAR2(20 BYTE), HIER_CODE VARCHAR2(20 BYTE),NODE_CODE VARCHAR2(200 BYTE))';
END IF;
CURSOR C_HIER
IS
SELECT DISTINCT HIER_CODE FROM TMP$UOM_COMBO_GEN WHERE UOM_ID=P_UOM_ID;
FOR HIER IN C_HIER
LOOP
IF C_HIER%ROWCOUNT = 1 THEN
LV_SQL2 := '(SELECT UOM_ID, NODE_CODE '||HIER.HIER_CODE||' FROM TMP$UOM_COMBO_GEN WHERE UOM_ID='''||P_UOM_ID||''' AND HIER_CODE='''||HIER.HIER_CODE||''')'||HIER.HIER_CODE;
LV_SORT := ' ORDER BY '||HIER.HIER_CODE||'';
LV_SQL := 'SELECT * FROM ' || LV_SQL2;
ELSE
LV_SQL3 := ' LEFT OUTER JOIN(SELECT NODE_CODE '||HIER.HIER_CODE||' FROM TMP$UOM_COMBO_GEN WHERE UOM_ID='''||P_UOM_ID||''' AND HIER_CODE='''||HIER.HIER_CODE||''')'||HIER.HIER_CODE ||' ON 1=1';
LV_SORT := LV_SORT||','||HIER.HIER_CODE||'';
LV_SQL := LV_SQL || LV_SQL3;
END IF;
END LOOP;
I am getting the following error.
Error(17,10): PLS-00103: Encountered the symbol "C_HIER" when expecting one of the following: := . ( # % ;
Well a table once created is stored in database and u can refer it from wherever u want to refer in the schema .
Also there a change may be required in your code in the following part
SELECT COUNT(*)
INTO ln_cnt
FROM User_Tables
WHERE table_name = 'TMP$UOM_COMBO_GEN';
IF ln_cnt > 0 THEN -- means only if table exists u want to create the table which will
--throw an exception if table is already there ,
--so better equate it to 0
EXECUTE IMMEDIATE ' CREATE TABLE TMP$UOM_COMBO_GEN (UOM_ID VARCHAR2(20 BYTE), HIER_CODE VARCHAR2(20 BYTE),NODE_CODE VARCHAR2(200 BYTE))';
END IF;
Now , if u really have a requirement to create a new table every time some condition is true/false and u then want to select the table in a cursor do something like following by using reference cursors
create or replace procedure abc(Table_name varchar2 , param_list varchar2 , where_clause varchar2) is
c_hier sys_refcursor ;
LV_SQL2 varchar2(2000) ;
LV_SORT varchar2(2000) ;
LV_SQL varchar2(2000) ;
LV_SQL3 varchar2(2000) ;
begin
SELECT COUNT(*)
INTO ln_cnt
FROM User_Tables
WHERE table_name = Table_name; -- Use any table here
IF ln_cnt = 0 THEN
EXECUTE IMMEDIATE ' CREATE TABLE '||Table_name||' '||param_list;
END IF;
open c_hier for 'SELECT DISTINCT '||param_list||' FROM '||table_name||' '||where_clause;
FOR HIER IN C_HIER
LOOP
IF C_HIER%ROWCOUNT = 1 THEN
LV_SQL2 := '(SELECT UOM_ID, NODE_CODE '||HIER.HIER_CODE||' FROM TMP$UOM_COMBO_GEN WHERE UOM_ID='''||P_UOM_ID||''' AND HIER_CODE='''||HIER.HIER_CODE||''')'||HIER.HIER_CODE;
LV_SORT := ' ORDER BY '||HIER.HIER_CODE||'';
LV_SQL := 'SELECT * FROM ' || LV_SQL2;
ELSE
LV_SQL3 := ' LEFT OUTER JOIN(SELECT NODE_CODE '||HIER.HIER_CODE||' FROM TMP$UOM_COMBO_GEN WHERE UOM_ID='''||P_UOM_ID||''' AND HIER_CODE='''||HIER.HIER_CODE||''')'||HIER.HIER_CODE ||' ON 1=1';
LV_SORT := LV_SORT||','||HIER.HIER_CODE||'';
LV_SQL := LV_SQL || LV_SQL3;
END IF;
END LOOP;

How to get Numbers in number range by PL-Sql .?

here is my serial table.it has more than 1000 records.its with start number and end number.but between numbers not exist.
i need to add all number [start/between & end numbers] records in another temp table number by number
like below
EXIST TABLE
select concat(CARD_BULK_CODE,start_serial) startserial,concat(CARD_BULK_CODE,end_serial) endserial
from TSR_BULK_CARD_SERIALS
---------------------------
STARTSERIAL ENDSERIAL |
---------------------------
18126944 18126946 |
18141101 18141122 |
15150722 15150729 |
19069303 19069317 |
---------------------------
REQUIRED TABLE
-----------
SERIAL_NO |
-----------
18126944
18126945
18141101
18141102
....
-----------
seem its need pl-sql to implement this.
please help me to sort out this issue
I tried with below query with the help of dual.
but its very slow and not yet got results :-) running more than 1 Hour
select distinct concat(t.CARD_BULK_CODE,t.START_SERIAL)+level-1 SERIAL
from TSR_BULK_CARD_SERIALS t, dual
connect by level-1<=(concat(t.CARD_BULK_CODE,t.END_SERIAL ))-concat(t.CARD_BULK_CODE,t.START_SERIAL)
order by 1
EDIT :
Dear Alen & Dba.i tried with your ones and below error occured.
DECLARE
l_st NUMBER;
l_en NUMBER;
BEGIN
FOR rec IN (select concat(card_bulk_code, start_serial) startserial,concat(card_bulk_code, end_serial) endserial from tsr_bulk_card_serials)
LOOP
l_st := rec.startserial;
l_en := rec.endserial;
FOR rec1 IN l_st..l_en
LOOP
INSERT INTO temp(serial_no) values(rec1);
END LOOP;
END LOOP;
COMMIT;
END;
Error at line 1
ORA-01426: numeric overflow
ORA-06512: at line 9
Script Terminated on line 1.
One way to do it without resorting to plsql
WITH ranges AS
(
SELECT CONCAT(CARD_BULK_CODE, start_serial) startserial,
CONCAT(CARD_BULK_CODE, end_serial) endserial
FROM TSR_BULK_CARD_SERIALS
),
numbers(n) AS (
SELECT 0 n
FROM dual
UNION ALL
SELECT n + 1
FROM numbers
WHERE n <=
(
SELECT MAX(endserial - startserial)
FROM ranges
)
)
SELECT t.startserial + n.n SERIAL_NO
FROM ranges t JOIN numbers n
ON n.n <= t.endserial - t.startserial
ORDER BY SERIAL_NO
Here is SQLFiddle demo
Just write some PL/SQL - iterate through your table and insert rows in the temp table.
declare
l_start number;
l_end number;
begin
for r_rec in (select to_number(concat(card_bulk_code, start_serial)) startserial
, to_number(concat(card_bulk_code, end_serial)) endserial
from tsr_bulk_card_serials )
loop
l_start := r_rec.startserial;
l_end := r_rec.endserial;
for l_i in l_start..l_end loop
insert into your_temp_table;
end loop;
end loop;
end;
Try like this,
WITH t(ST, EN) AS
(
SELECT 18126944, 18126946 FROM dual
UNION
SELECT 18141101, 18141122 FROM dual
UNION
SELECT 15150722, 15150729 FROM dual
UNION
SELECT 19069303 , 19069317 FROM dual
)
SELECT DISTINCT st + LEVEL -1
FROM t
CONNECT BY LEVEL <= (SELECT en - st + 1 FROM DUAL)
ORDER BY 1;
/
Try something like this for PL/SQL,
DECLARE
l_st NUMBER;
l_en NUMBER;
BEGIN
FOR rec IN (SELECT * FROM t)
LOOP
l_st := rec.st;
l_en := rec.en;
FOR rec1 IN l_st..l_en
LOOP
INSERT INTO <your_tab>;
END LOOP;
END LOOP;
COMMIT;
END;
DECLARE
l_st NUMBER (20);
l_en NUMBER (20);
testnum NUMBER (4);
BEGIN
FOR rec IN (SELECT CONCAT (card_bulk_code, start_serial) startserial,CONCAT (card_bulk_code, end_serial) endserial FROM tsr_bulk_card_serials)
LOOP
l_st := TO_NUMBER (rec.startserial);
l_en := TO_NUMBER (rec.endserial);
testnum := l_en - l_st;
DBMS_OUTPUT.put_line (l_st);
DBMS_OUTPUT.put_line (l_en);
IF l_st < l_en
THEN
FOR rec1 IN 0 .. testnum
LOOP
l_st := l_st + 1;
INSERT INTO temp(serial_no) VALUES (l_st);
END LOOP;
END IF;
END LOOP;
COMMIT;
END;
above code helped me to sorted my issue
thanks all :-)