Prime Number using GOTO statement in PL/SQL - sql

This is my code for Prime Number using goto statement
set serveroutput on;
SQL>
SQL> declare
2 msg varchar2 (30);
3 n pls_integer := 83;
4
5 begin
6 for i in 2..round( sqrt(n) ) loop
7 if n mod i=0 then
8 msg := ' is not a prime number';
9 goto when_prime;
10 end if;
11 end loop;
12
13 msg := ' is a prime number';
14
15 <>
16 dbms_output.put_line(to_char(n) || msg);
17 end;
18 /
I'm getting the following error :
<>
*
ERROR at line 15:
ORA-06550: line 15, column 1:
PLS-00103: Encountered the symbol ">" when expecting one of the following:
( begin case declare end exception exit for goto if loop mod
null pragma raise return select update while with
<an identifier> <a double-quoted delimited-identifier>
<a bind variable> << continue close current delete fetch lock
insert open rollback savepoint set sql execute commit forall
merge pipe purge
ORA-06550: line 16, column 40:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
. ( ) , * % & - + / at mod remainder rem <an exponent (**)>
and or || multiset
I want to check prime number or not a prime number using goto statement

You are not properly declaring the when_prime label.
Just replace this:
<>
With:
<<when_prime>>
Demo on DB Fiddle:
dbms_output:
83 is a prime number

You misused the label declaration section, it should be wrapped in << >> and not < >
Your code should be something like this:
SQL> DECLARE
2 MSG VARCHAR2(30);
3 N PLS_INTEGER := 83;
4 BEGIN
5 FOR I IN 2..ROUND(SQRT(N)) LOOP
6 IF N MOD I = 0 THEN
7 MSG := ' is not a prime number';
8 GOTO WHEN_PRIME;
9 END IF;
10 END LOOP;
11
12 MSG := ' is a prime number';
13 << WHEN_PRIME >>
14 DBMS_OUTPUT.PUT_LINE(TO_CHAR(N) || MSG);
15 END;
16 /
83 is a prime number
PL/SQL procedure successfully completed.
SQL>
UPDATE - Important
May be irrelevant for the error you are getting but you can directly use the following query to find the prime number:
SQL> WITH NUMBR AS (SELECT 83 NUMBR FROM DUAL)
2 SELECT NUMBR,
3 CASE WHEN SUM(CASE WHEN MOD(NUMBR, LEVEL) = 0
4 THEN 1 END) = 1
5 THEN 'prime'
6 ELSE 'not prime'
7 END AS "Prime?"
8 FROM NUMBR
9 CONNECT BY LEVEL <= FLOOR(NUMBR / 2)
10 GROUP BY NUMBR;
NUMBR Prime?
---------- ---------
83 prime
SQL>
Cheers!!

Related

IF condition containing IN operator inside ORACLE Trigger is not working

I have a trigger that uses IF condition with IN operator and two variables v_audit_user and v_evdnse_user inside IN. Both variables are containing comma separated ID values. The trigger gets compiled successfully with no errors. I am not understanding why the IF condition with IN is not working. When I select the function that assigns value to the variables independently, I do see the comma separated values, so nothing is wrong with function (see screenshot).
create or replace TRIGGER TRG_CHK_HRCQA_CASE_ACTIONS
AFTER INSERT ON KDD_CASE_ACTIONS
FOR EACH ROW
DECLARE
user_audit kdd_review_owner.OWNER_ID%TYPE; /* The user that is displayed in audit */
user_evdnse kdd_review_owner.OWNER_ID%TYPE; /* The user that took action in evidence tab */
v_audit_user NUMBER; /* The HRCO/QA user from audit tab */
v_evdnse_user NUMBER; /* The HRCO/QA user from evidence tab */
LV_ERRORCODE VARCHAR2(1000);
BEGIN
/* pass the username into the variables */
SELECT kro.OWNER_ID into user_audit from kdd_review_owner kro where kro.OWNER_SEQ_ID = :NEW.ACTION_BY_ID;
SELECT kro.OWNER_ID into user_evdnse from kdd_review_owner kro where kro.OWNER_SEQ_ID = :NEW.ACTION_BY_ID;
/* fetch the comma separated IDs */
v_audit_user := F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID,user_audit,'AUDIT');
v_evdnse_user := F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID,user_evdnse,'EVDNSE');
-- select ENTITY_ID into v_evdnse_user from table(f_get_arg_table(F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID,user_evdnse,'EVDNSE')));
/* If the action taken is by QA or HRCO role */
IF (:NEW.ACTION_SEQ_ID in (v_audit_user,v_evdnse_user))
THEN
/* then insert record in the SC_HRCQA_CASE_ACTIONS table with IS_HRCO_QA flag as Y */
Insert into SC_HRCQA_CASE_ACTIONS (ACTION_SEQ_ID,ACTION_BY_ID,ACTION_TS,STATUS_CD,CASE_INTRL_ID,ACTION_ID,NEW_CASE_OWNR_ASSGN_ID,CASE_DUE_TS,PREV_CASE_OWNR_ASSGN_ID,IS_HRCO_QA)
values (:NEW.ACTION_SEQ_ID, :NEW.ACTION_BY_ID, :NEW.ACTION_TS, :NEW.STATUS_CD, :NEW.CASE_INTRL_ID, :NEW.ACTION_ID, :NEW.NEW_CASE_OWNR_ASSGN_ID, :NEW.CASE_DUE_TS, :NEW.PREV_CASE_OWNR_ASSGN_ID,'Y');
-- ELSE
--
-- /* else the logged in user is NOT HRCO/QA hence insert record in the SC_HRCQA_CASE_ACTIONS table with IS_HRCO_QA flag as N */
--
-- Insert into SC_HRCQA_CASE_ACTIONS (ACTION_SEQ_ID,ACTION_BY_ID,ACTION_TS,STATUS_CD,CASE_INTRL_ID,ACTION_ID,NEW_CASE_OWNR_ASSGN_ID,CASE_DUE_TS,PREV_CASE_OWNR_ASSGN_ID,IS_HRCO_QA)
-- values (:NEW.ACTION_SEQ_ID, :NEW.ACTION_BY_ID, :NEW.ACTION_TS, :NEW.STATUS_CD, :NEW.CASE_INTRL_ID, :NEW.ACTION_ID, :NEW.NEW_CASE_OWNR_ASSGN_ID, :NEW.CASE_DUE_TS, :NEW.PREV_CASE_OWNR_ASSGN_ID,'N');
END IF;
EXCEPTION
WHEN OTHERS THEN LV_ERRORCODE := SQLCODE;
INSERT INTO KDD_LOGS_MSGS (LOG_DT, LOG_INFO_TX, REMARK_TX)
VALUES (SYSDATE,'ErrorCode - ' || LV_ERRORCODE,'TRG_CHK_HRCQA_CASE_ACTIONS');
END;
You cannot pass a comma-delimited string stored in a single variable to an IN condition and expect it to be parsed as multiple values as it is not.
If you want to use a single variable containing a delimited list then you will need to use string functions to find a sub-string match:
create or replace TRIGGER TRG_CHK_HRCQA_CASE_ACTIONS
AFTER INSERT ON KDD_CASE_ACTIONS
FOR EACH ROW
DECLARE
v_owner_id kdd_review_owner.OWNER_ID%TYPE;
v_audit_user VARCHAR2(1000);
v_evdnse_user VARCHAR2(1000);
LV_ERRORCODE VARCHAR2(1000);
BEGIN
SELECT OWNER_ID
into v_owner_id -- You only need one variable here
from kdd_review_owner
where OWNER_SEQ_ID = :NEW.ACTION_BY_ID;
v_audit_user := F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID, v_owner_id, 'AUDIT');
v_evdnse_user := F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID, v_owner_id, 'EVDNSE');
IF ','||v_audit_user||','||v_evdnse_user||',' LIKE '%,'||:NEW.ACTION_SEQ_ID||',%'
THEN
Insert into SC_HRCQA_CASE_ACTIONS (
ACTION_SEQ_ID, ACTION_BY_ID, ACTION_TS, STATUS_CD, CASE_INTRL_ID,
ACTION_ID, NEW_CASE_OWNR_ASSGN_ID, CASE_DUE_TS, PREV_CASE_OWNR_ASSGN_ID, IS_HRCO_QA
) values (
:NEW.ACTION_SEQ_ID, :NEW.ACTION_BY_ID, :NEW.ACTION_TS, :NEW.STATUS_CD, :NEW.CASE_INTRL_ID,
:NEW.ACTION_ID, :NEW.NEW_CASE_OWNR_ASSGN_ID, :NEW.CASE_DUE_TS, :NEW.PREV_CASE_OWNR_ASSGN_ID,'Y'
);
END IF;
EXCEPTION
WHEN OTHERS THEN LV_ERRORCODE := SQLCODE;
INSERT INTO KDD_LOGS_MSGS (LOG_DT, LOG_INFO_TX, REMARK_TX)
VALUES (SYSDATE,'ErrorCode - ' || LV_ERRORCODE,'TRG_CHK_HRCQA_CASE_ACTIONS');
END;
/
I don't have your tables so I'll try to illustrate it using my own code.
This is what you're doing now: to us (humans), it is obvious that L_NEW_ID (its value is 10) is contained in L_VAR1 (its value is '10,20'). However, Oracle doesn't recognize that and returns "Not OK":
SQL> declare
2 -- does L_NEW_ID exist in L_VAR1 and L_VAR2 (using your code)?
3 l_new_id number := 10;
4 --
5 l_var1 varchar2(20) := '10,20';
6 l_var2 varchar2(20) := '30,40';
7 begin
8 if l_new_id in (l_var1, l_var2) then
9 dbms_output.put_line('OK');
10 else
11 dbms_output.put_line('Not OK');
12 end if;
13 end;
14 /
Not OK
PL/SQL procedure successfully completed.
SQL>
So, what to do? One option is to split variables to rows and then check whether search value (10, right?) exists in such a list of values (rows). The result is - as you can see - "OK":
SQL> declare
2 l_new_id number := 10;
3 --
4 l_var1 varchar2(20) := '10,20';
5 l_var2 varchar2(20) := '30,40';
6 l_cnt number;
7 begin
8 -- count how many times L_NEW_ID exists in L_VAR1 nad L_VAR2
9 select count(*)
10 into l_cnt
11 from (-- split L_VAR1 into rows
12 select regexp_substr(l_var1, '[^,]+', 1, level) val
13 from dual
14 connect by level <= regexp_count(l_var1, ',') + 1
15 union all
16 -- split L_VAR2 into rows
17 select regexp_substr(l_var2, '[^,]+', 1, level)
18 from dual
19 connect by level <= regexp_count(l_var2, ',') + 1
20 ) x
21 where x.val = l_new_id;
22
23 if l_cnt > 0 then
24 dbms_output.put_line('OK');
25 else
26 dbms_output.put_line('Not OK');
27 end if;
28 end;
29 /
OK
PL/SQL procedure successfully completed.
SQL>
Just to verify it, let's change L_NEW_ID value to e.g. 99 and see what happens; as expected, "Not OK" as 99 isn't contained in 10, 20 nor 30, 40.
SQL> l2
2* l_new_id number := 10;
SQL> c/10/99
2* l_new_id number := 99;
SQL> /
Not OK
PL/SQL procedure successfully completed.
SQL>

Like operator with % in oracle plsql cursor

I cannot pass the like operator with % in the cursor sql stmt, getting code error, Can you help
SQL> l
1 CREATE OR REPLACE PROCEDURE cleanuptab (
2 isrc_tns VARCHAR2
3 )
4 IS
5 sql_stmt VARCHAR2(500);
6 errm VARCHAR2(2000);
7 refcur SYS_REFCURSOR;
8 v_tabs VARCHAR2(50);
9 BEGIN
10 OPEN refcur FOR 'SELECT table_name FROM dba_tables where table_name like '%''||isrc_tns||''%' and owner='DBASCHEMA'';
11 LOOP
12 BEGIN
13 FETCH refcur INTO v_tabs;
14 EXIT WHEN refcur%NOTFOUND;
15 EXECUTE IMMEDIATE 'drop table DBASCHEMA.'
16 ||v_tabs
17 || ' purge';
18 dbms_output.Put_line('DROPPED '
19 ||v_tabs);
20 EXCEPTION
21 WHEN OTHERS THEN
22 dbms_output.Put_line( 'TABLE NOT FOUND: '
23 ||v_tabs);
24 CONTINUE;
25 END;
26 END LOOP;
27 close refcur;
28* END;
SQL> /
Warning: Procedure created with compilation errors.
SQL> show error
Errors for PROCEDURE CLEANUPTAB:
LINE/COL ERROR
-------- -----------------------------------------------------------------
10/79 PLS-00103: Encountered the symbol "%" when expecting one of the
following:
* & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between using || multiset member submultiset
The symbol "* was inserted before "%" to continue.
10/96 PLS-00103: Encountered the symbol "%" when expecting one of the
following:
* & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
LINE/COL ERROR
-------- -----------------------------------------------------------------
like4 likec between using || member submultiset
I am trying to pass the like stmt & owner condition so that i can get those tables & drop. Pls help to review
Regards
Kannan
Why not try it without OPEN/FETCH/NOTFOUND, without all the local variables, without the danger of SQL injection, with less lines of codes:
CREATE OR REPLACE PROCEDURE cleanuptab (
isrc_tns VARCHAR2
)
IS
BEGIN
FOR v_tabs IN (SELECT table_name FROM dba_tables WHERE table_name LIKE '%' || isrc_tns || '%' AND owner = 'DBASCHEMA')
LOOP
BEGIN
EXECUTE IMMEDIATE 'drop table DBASCHEMA.' || v_tabs.table_name || ' purge';
dbms_output.put_line('DROPPED ' || v_tabs.table_name );
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('FAILED TO DROP ' || v_tabs.table_name);
END;
END LOOP;
END;

PL SQL Loop Table after insert and update

I'm trying loop through a table called broker after an insert to a different table called appointment and update a value on the broker table this what i have. When i try to create the trigger it comes up with an error saying "Trigger created with compilation errors"
CREATE OR REPLACE TRIGGER broker_level_trigger
AFTER INSERT ON appointment
DECLARE
counter integer := 1;
BEGIN
for o in (SELECT * FROM broker)
loop
SELECT COUNT(appointment.broker_id) INTO app_number FROM appointment INNER JOIN broker ON broker.broker_id = appointment.broker_id WHERE broker.broker_id = counter;
IF app_number > 15 THEN
UPDATE broker SET broker_level = 'gold' WHERE broker_id = counter;
counter := counter + 1;
end loop;
end;
/
The broker table has a field called broker_level and it changes based on the appointments, i want it to change if the broker_id field on appointments gets to more then 15
show err is a wonderful thing. (I created dummy tables you use).
SQL> CREATE OR REPLACE TRIGGER broker_level_trigger
2 AFTER INSERT ON appointment
3 DECLARE
4 counter integer := 1;
5 BEGIN
6 for o in (SELECT * FROM broker)
7 loop
8 SELECT COUNT(appointment.broker_id)
9 INTO app_number
10 FROM appointment INNER JOIN broker
11 ON broker.broker_id = appointment.broker_id
12 WHERE broker.broker_id = counter;
13
14 IF app_number > 15 THEN
15 UPDATE broker SET
16 broker_level = 'gold'
17 WHERE broker_id = counter;
18 counter := counter + 1;
19
20 end loop;
21 end;
22 /
Warning: Trigger created with compilation errors.
SQL> show err
Errors for TRIGGER BROKER_LEVEL_TRIGGER:
LINE/COL ERROR
-------- -----------------------------------------------------------------
18/7 PLS-00103: Encountered the symbol "LOOP" when expecting one of
the following:
if
If you look closer, you'll see that IF misses its END IF. Let's add it:
SQL> CREATE OR REPLACE TRIGGER broker_level_trigger
2 AFTER INSERT ON appointment
3 DECLARE
4 counter integer := 1;
5 BEGIN
6 for o in (SELECT * FROM broker)
7 loop
8 SELECT COUNT(appointment.broker_id)
9 INTO app_number
10 FROM appointment INNER JOIN broker
11 ON broker.broker_id = appointment.broker_id
12 WHERE broker.broker_id = counter;
13
14 IF app_number > 15 THEN
15 UPDATE broker SET
16 broker_level = 'gold'
17 WHERE broker_id = counter;
18 counter := counter + 1;
19 END IF; --> missing
20 end loop;
21 end;
22 /
Warning: Trigger created with compilation errors.
SQL> show err
Errors for TRIGGER BROKER_LEVEL_TRIGGER:
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/5 PL/SQL: SQL Statement ignored
7/12 PLS-00201: identifier 'APP_NUMBER' must be declared
8/7 PL/SQL: ORA-00904: : invalid identifier
12/5 PL/SQL: Statement ignored
12/8 PLS-00201: identifier 'APP_NUMBER' must be declared
APP_NUMBER is missing now; you use it, but never declared it. Let's do it now:
SQL> CREATE OR REPLACE TRIGGER broker_level_trigger
2 AFTER INSERT ON appointment
3 DECLARE
4 counter integer := 1;
5 app_number number; --> missing
6 BEGIN
7 for o in (SELECT * FROM broker)
8 loop
9 SELECT COUNT(appointment.broker_id)
10 INTO app_number
11 FROM appointment INNER JOIN broker
12 ON broker.broker_id = appointment.broker_id
13 WHERE broker.broker_id = counter;
14
15 IF app_number > 15 THEN
16 UPDATE broker SET
17 broker_level = 'gold'
18 WHERE broker_id = counter;
19 counter := counter + 1;
20 END IF; --> missing
21 end loop;
22 end;
23 /
Trigger created.
SQL>
That would be it.
If you don't use SQL*Plus but some other tool, you can always query user_errors:
Warning: Trigger created with compilation errors.
SQL> select line, position, text from user_errors where name = 'BROKER_LEVEL_TRIGGER' order by sequence;
LINE POSITION TEXT
----- --------- ------------------------------------------------------------
8 12 PLS-00201: identifier 'APP_NUMBER' must be declared
9 7 PL/SQL: ORA-00904: : invalid identifier
7 5 PL/SQL: SQL Statement ignored
13 8 PLS-00201: identifier 'APP_NUMBER' must be declared
13 5 PL/SQL: Statement ignored
SQL>

my trigger wont print what i want it to

so im a student working in Oracle SQL and i wrote a trigger to notify me if the item quantity is under a certain value. my trigger was created without compilation errors but when i test it i do not see the output that i want... I am sure there may be better ways to do certain parts of this but i am concerned mostly with how to get it to print to the command line. also if possible i would like the first if statement to contain a break statement so that the quantity cannot be less than 0. is that done by addint 'BREAK;' before the 'END IF;'?
SQL> #345lowqtytrigger
SQL> CREATE OR REPLACE TRIGGER low_qty_trigger
2 BEFORE INSERT OR UPDATE OF vnd_itm_qty ON Vending_Machine_Item
3 FOR EACH ROW
4 DECLARE
5 tempstr varchar2(1000);
6 name varchar2(1000);
7 vndadd varchar2(1000);
8 tempint int;
9 cursor itm_des_cursor is
10 SELECT itm_des FROM item WHERE itm_id = item.itm_id;
11 cursor vnd_addr_cursor is
12 SELECT vnd_addr FROM Vending_Machine WHERE vnd_id = Vending_Machine.vnd_id;
13 BEGIN
14 open itm_des_cursor;
15 fetch itm_des_cursor into name;
16 open vnd_addr_cursor;
17 fetch vnd_addr_cursor into vndadd;
18 IF :NEW.vnd_itm_qty < 0 THEN
19 tempstr := concat(:new.vnd_id,concat(' can not have less than 0 quantity for ',name));
20 dbms_output.put_line(tempstr);
21 end if;
22 tempint := :new.vnd_itm_qty_max*.15;
23 IF
24 :NEW.vnd_itm_qty <= tempint
25 and
26 :NEW.vnd_itm_qty >= 0
27 THEN
28 tempstr := concat('There will be less than ',
29 concat(to_char(tempint),
30 concat(' of ',
31 concat(name,
32 concat(' in Vending Machine ',
33 concat(to_char(:new.vnd_id),
34 concat(' located at ',vndadd)))))));
35 dbms_output.put_line(tempstr);
36 END IF;
37 close itm_des_cursor;
38 close vnd_addr_cursor;
39 END;
40 /
Trigger created.
SQL> SET ECHO OFF;
No errors.
SQL> spool off;
TEST CASE
SQL> update vending_machine_item set vnd_itm_qty = 1 where vnd_id = 956 and itm_id = 193;
1 row updated.
How are you testing this? It has to be in an interactive session to see any output generated by dbms_output. Try an update on vending_machine_item from a sql*plus session with set serveroutput on.

split CLOB field into table like structure

I have field in a Oracle database of type CLOB. I would like to split this field in several columns and rows. Here's an example of the content:
4:true5:false24:<p>option sample 1.</p>4:true22:<p>option sample 2.</p>5:false23:<p>option sample 3.</p>5:false22:<p>option sample 4.</p>5:false
The result should look like this:
ID LEVEL ANSWER_OPTION VALUE
1 3 option sample 3 false
1 4 option sample 4 false
2 3 option sample 3 false
4 3 option sample 3 true
3 2 option sample 2 false
1 2 option sample 2 true
2 1 option sample 1 true
2 4 option sample 4 false
4 1 option sample 1 false
2 2 option sample 2 false
4 2 option sample 2 false
1 1 option sample 1 false
3 4 option sample 4 false
4 4 option sample 4 false
3 3 option sample 3 false
3 1 option sample 1 true
We have made the following statement which created the result above.
with guest_string as
( select qsn.id id
, dbms_lob.substr( qsn.guest, 2000, 1 ) answer_options
from mneme_question qsn
where qsn.id < 10
)
select distinct id
, level
, substr(regexp_substr( answer_options'<p>[^<]+', 1, level, 'i'), 4) ANSWER_OPTION
, substr(regexp_substr( answer_options, '(true|false)', regexp_instr( answer_options, '</p>', 1, 1), level, 'i'), 1) VALUE
from guest_string
connect by regexp_substr( answer_options, '<p>[^<]+', 1, level, 'i') is not null
The problem with this code is it takes way to long to split all records we have. We had to cut it off at 10 rows (5 row take 0.25 sec, 10 takes 16 seconds, 15 rows takes about over 2,5 minutes). We currently have 30000 rows and they will grow. At the moment we cannot change the software to change the datamodel, so we will have to do this ad hoc.
Our current approach is to create a procedure that will be called for each record, but it would be better to have a faster parsing. Does anybody have a suggestion how to create a script that can do this in a reasonable time. We can do this at night time, but preferably it shouldn't take longer than 2 minutes.
BTW in the future we could build some sort of mechanism to determine which records have already been parsed, but that also requires some form of detecting already parsed fields that have changed in the mean time. We don't have time to do that yet, so for now we need crude parsing as fast as possible.
Thanks
Here is a different approach.
The code may not be as nice as it can, and you will probably have to fix some small things...
I checked it on 11g (couldn't find 10g) and used your input as the values in my clob column.
For 10 rows (all with the same input as you gave as example),
original query: 9.8 sec
new query: 0.08 sec
I used a pipelined function, here is the code:
create or replace type t_parse is object(idd number, levell number, answer_option varchar2(128), valuee varchar2(4000));
/
create or replace type tab_parse is table of t_parse;
/
create or replace function split_answers return tab_parse
pipelined is
cursor c is
select * from mneme_question;
str_t clob;
phraseP varchar2(128);
phraseV varchar2(8);
i1s number;
i1e number;
i2s number;
levell number;
begin
for r in c loop
str_t := r.guest;
levell := 1;
while str_t is not null loop
i1s := dbms_lob.instr(str_t, '<p>', 1, 1) + 3;
if i1s = 3 then
str_t := '';
else
i1e := dbms_lob.instr(str_t, '</p>', 1, 1);
phraseP := dbms_lob.substr(str_t, i1e - i1s, i1s);
str_t := dbms_lob.substr(str_t, offset => i1e + 4);
i2s := dbms_lob.instr(str_t, 'true', 1, 1) ;
if i2s = 0 then
i2s := dbms_lob.instr(str_t, 'false', 1, 1) ;
if i2s = 0 then
str_t := '';
else
phraseV := dbms_lob.substr(str_t, 5, i2s);
pipe row(t_parse(r.id, levell, phraseP, phraseV));
levell := levell + 1;
end if;
else
phraseV := dbms_lob.substr(str_t, 4, i2s);
pipe row(t_parse(r.id, levell, phraseP, phraseV));
levell := levell + 1;
end if;
end if;
end loop;
end loop;
return;
end split_answers;
/
new query should be like:
select * from table(split_answers);
There is some function whis returning pipelined table:
CREATE OR REPLACE FUNCTION split_clob(p_clob IN CLOB DEFAULT NULL,
p_varchar IN VARCHAR2 DEFAULT NULL,
p_separator IN VARCHAR2)
RETURN varchar_set
PIPELINED IS
l_clob CLOB;
BEGIN
l_clob := nvl(p_clob,
to_clob(p_varchar));
FOR rec IN (
WITH vals AS
(SELECT CAST(TRIM(regexp_substr(l_clob,
'[^'||p_separator||']+',
1,
levels.column_value)) AS
VARCHAR2(320)) AS val
FROM TABLE(CAST(MULTISET
(SELECT LEVEL
FROM dual
CONNECT BY LEVEL <=
length(regexp_replace(l_clob,
'[^'||p_separator||']+')) + 1) AS
sys.odcinumberlist)) levels)
SELECT val FROM vals)
LOOP
PIPE ROW(rec.val);
END LOOP;
RETURN;
END;
U can use it like this:
-with table with clob
SELECT t2.column_value FROM my_table t, TABLE(split_clob(p_clob => t.clob_column,p_separator => ',')) t2
-or with varchar too
SELECT * FROM TABLE(split_clob(p_varchar => '1,2,3,4,5,6, 7, 8, 9', p_separator => ','))