How write a PL/SQL program that prints out string which looking like xml format - oracle

Input String : “a4b4c2d9d9c2e6e6b4s2o1o1s2a4w2r8r8k3g5g5k3w2”
I tried this code as first step:
declare
word varchar2(50) := 'a4b4c2d9d9c2e6e6b4s2o1o1s2a4w2r8r8k2g5g5k2w2';
num number := length(word)/2;
name_array dbms_sql.varchar2_table;
begin
dbms_output.put_line(word);
FOR i IN 1..num LOOP
name_array(i) := substr(word, -2*i, 2);
END LOOP;
FOR i IN name_array.FIRST .. name_array.LAST LOOP
dbms_output.put_line(name_array(i));
END LOOP;
end;
This code creates only an array of string. Not xml format. I need this output:
Which SQL functions,conditional clauses... do I need to use?

Oracle Setup:
CREATE OR REPLACE TYPE CHARS_TABLE IS TABLE OF CHAR(2);
/
CREATE OR REPLACE TYPE INTEGERS_TABLE IS TABLE OF INTEGER;
/
PL/SQL:
This assumes a well-formed set of character pairs and just indents each pair to the appropriate level:
DECLARE
word VARCHAR2(50) := 'a4b4c2d9d9c2e6e6b4s2o1o1s2a4w2r8r8k2g5g5k2w2';
num PLS_INTEGER := LENGTH( word ) / 2;
name_array CHARS_TABLE := CHARS_TABLE();
depth_array INTEGERS_TABLE := INTEGERS_TABLE();
open_array INTEGERS_TABLE := INTEGERS_TABLE();
BEGIN
name_array.EXTEND( num );
depth_array.EXTEND( num );
open_array.EXTEND( num );
name_array(1) := SUBSTR( word, 1, 2 );
depth_array(1) := 1;
open_array(1) := 1;
FOR i IN 2 .. num LOOP
name_array(i) := SUBSTR( word, 2*i - 1, 2 );
open_array(i) := 1;
FOR j IN 1 .. i-1 LOOP
IF name_array(j) = name_array(i) THEN
open_array(i) := -open_array(i);
END IF;
END LOOP;
depth_array(i) := depth_array(i-1) + open_array(i);
END LOOP;
FOR i IN 1 .. num LOOP
FOR j IN 2 .. depth_array(i) + CASE open_array(i) WHEN 1 THEN 0 ELSE 1 END LOOP
DBMS_OUTPUT.PUT( ' ' );
END LOOP;
DBMS_OUTPUT.PUT_LINE( name_array(i) );
END LOOP;
END;
/
Output:
a4
b4
c2
d9
d9
c2
e6
e6
b4
s2
o1
o1
s2
a4
w2
r8
r8
k2
g5
g5
k2
w2
Update - Simpler Stack-Based Version:
DECLARE
word CONSTANT VARCHAR2(50) := 'a4b4c2d9d9c2e6e6b4s2o1o1s2a4w2r8r8k2g5g5k2w2';
num CONSTANT PLS_INTEGER := LENGTH( word ) / 2;
name_array CHARS_TABLE := CHARS_TABLE();
depth PLS_INTEGER := 0;
name CHAR(2);
PROCEDURE indent( depth PLS_INTEGER, name CHAR )
IS
BEGIN
FOR j IN 2 .. depth LOOP
DBMS_OUTPUT.PUT( ' ' );
END LOOP;
DBMS_OUTPUT.PUT_LINE( name );
END;
BEGIN
name_array.EXTEND( num );
FOR i IN 1 .. num LOOP
name := SUBSTR( word, 2*i - 1, 2 );
IF depth > 0 AND name = name_array(depth) THEN
indent(depth,name);
depth := depth - 1;
ELSE
depth := depth - 1;
name_array(depth) := name;
indent(depth,name);
END IF;
END LOOP;
END;
/

DECLARE
vs_CurrentChar VARCHAR2(1);
vs_NextChar VARCHAR2(1);
vs_TempText VARCHAR2(100);
vs_InputText VARCHAR2(100) := 'abcdffdcba';
vn_LengthOfText NUMBER := 1;
vn_WhileIndex NUMBER := 1;
vs_Spaces VARCHAR(100);
BEGIN
vs_TempText := NULL;
vs_CurrentChar := substr(vs_InputText, vn_WhileIndex, vn_LengthOfText);
dbms_output.put_line(vs_CurrentChar);
WHILE vn_WhileIndex < length(vs_InputText) - 1 LOOP
vs_NextChar := substr(vs_InputText, vn_WhileIndex + 1, vn_LengthOfText);
EXIT WHEN vs_CurrentChar = vs_NextChar;
vs_TempText := vs_TempText || vs_CurrentChar;
vs_CurrentChar := vs_NextChar;
vs_Spaces := NULL;
FOR i IN 1 .. vn_WhileIndex LOOP
vs_Spaces := vs_Spaces || chr(9); --'*';
END LOOP;
dbms_output.put_line(vs_Spaces || vs_CurrentChar);
vn_WhileIndex := vn_WhileIndex + 1;
END LOOP;
dbms_output.put_line(vs_Spaces || vs_CurrentChar);
FOR i IN 1 .. length(vs_TempText) LOOP
vs_Spaces := substr(vs_Spaces, vn_LengthOfText, length(vs_Spaces) - 1);
vs_CurrentChar := substr(vs_TempText, -i, vn_LengthOfText);
dbms_output.put_line(vs_Spaces || vs_CurrentChar);
END LOOP;
END;
/
And output:
a
b
c
d
f
f
d
c
b
a
even, if you put '*'; instead of chr(9); then output will look like as:
a
*b
**c
***d
****f
****f
***d
**c
*b
a

Related

TOP with index variable oracle

I was trying to use the variable 'ind' to get the ROWNUM on my select, but everytime I try to use the variable there I get a error like:
ORA-01008: not all variables bound
or these two:
ORA-01403: no data found
ORA-06512: at line 10
DECLARE
texto VARCHAR2(255);
ind NUMBER := 0;
BEGIN
LOOP
ind := ind + 1;
IF ind > 3 THEN
EXIT;
END IF;
SELECT TEXTO_LOG
INTO texto
from table WHERE REGEXP_LIKE(TEXTO_LOG, 'Alteração') AND ROWNUM >= :ind AND ROWNUM <= :ind ;
dbms_output.put_line(substr(trim(texto), 1, instr(texto, ' ')));
dbms_output.put_line(substr(texto, 0, 100));
END LOOP;
END;
/
I searched and found someone telling that not all variables bound is a bug, I'm not sure if it's.
I tried the ROWNUM with different opperators. Any suggestions?
Usage of rownum is the problem here apart from other issues already answered. a predicate like rownum>=2 and rownum <=2 (and so on...till exit point) yield no result and thus no_data_found error
But as workaround put the rownum inside from clause and restrict it outside should work,
DECLARE
texto VARCHAR2(255);
ind NUMBER := 0;
BEGIN
LOOP
ind := ind + 1;
IF ind > 3
THEN
EXIT;
END IF;
SELECT texto_log
INTO texto
FROM (SELECT texto_log
,rownum myrownum
FROM TABLE
WHERE regexp_like(texto_log
,'Alteração'))
WHERE myrownum >= ind
AND myrownum <= ind;
dbms_output.put_line(substr(TRIM(texto)
,1
,instr(texto
,' ')));
dbms_output.put_line(substr(texto
,0
,100));
END LOOP;
END;
/
The error is that you are referring to :ind as if it were a bind variable, when it is not. It is in fact a variable declared in your DECLARE section.
You might try this
** Update **
As your query looks like it is faling, the reason perhaps is in the query itself. Run this and get the output and running separately
set serveroutput on size unlimited
DECLARE
texto VARCHAR2(255);
ind NUMBER := 0;
BEGIN
for r in 1..4
LOOP
ind := r + 1;
dbms_output.put_line ( q'[SELECT TEXTO_LOG
INTO texto
from table WHERE REGEXP_LIKE(TEXTO_LOG, 'Alteração') AND ROWNUM <= ind ;
dbms_output.put_line(substr(trim(texto), 1, instr(texto, ' ')));
dbms_output.put_line(substr(texto, 0, 100));]');
exit when ind > 3;
END LOOP;
END;
/
Although you can build it like this which is easier
DECLARE
texto VARCHAR2(255);
ind NUMBER := 0;
BEGIN
for r in 1..4
LOOP
ind := r + 1;
dbms_output.put_line(ind);
SELECT TEXTO_LOG
INTO texto
from table WHERE REGEXP_LIKE(TEXTO_LOG, 'Alteração') AND ROWNUM >= ind AND ROWNUM <= ind ;
dbms_output.put_line(substr(trim(texto), 1, instr(texto, ' ')));
dbms_output.put_line(substr(texto, 0, 100));
exit when ind > 3;
END LOOP;
END;
/
EXample
SQL> DECLARE
texto VARCHAR2(255);
ind NUMBER := 0;
BEGIN
for r in 1..4
LOOP
ind := r + 1;
dbms_output.put_line(ind);
exit when ind > 3;
END LOOP;
END;
/ 2 3 4 5 6 7 8 9 10 11 12
2
3
4
PL/SQL procedure successfully completed.
SQL>
With implicit cursor
DECLARE
-- texto VARCHAR2(255);
ind NUMBER := 0;
BEGIN
FOR i IN (SELECT TEXTO_LOG FROM table WHERE REGEXP_LIKE(TEXTO_LOG, 'Alteração'))
LOOP
ind:=ind+1;
EXIT WHEN ind >3;
DBMS_OUTPUT.PUT_LINE(SUBSTR(TRIM(i.TEXTO_LOG), 1, INSTR(i.TEXTO_LOG, ' ')));
DBMS_OUTPUT.PUT_LINE(SUBSTR(i.TEXTO_LOG, 0, 100));
END LOOP;
END;

Reading two dimensional pl/sql array

I am able to insert values but failed to retrieve values. Thanks in anticipation.
declare
type type1 is table of number;
type data_type is table of type1;
y data_type;
begin
y := data_type();
y.extend(100);
for i in 1..100 loop
y(i) := type1();
y(i).extend(100);
for j in 1..100 loop
y(i)(j) := i+j;
end loop;
end loop;
end;
If I understand well, you need a way to scan your arrays;
this could be a way:
declare
type type1 is table of number;
type data_type is table of type1;
y data_type;
k number := 2;
begin
y := data_type();
y.extend(k);
for i in 1..k loop
y(i) := type1();
y(i).extend(k);
for j in 1..k loop
y(i)(j) := i+j;
end loop;
end loop;
-- scanning
for i in y.first .. y.last loop
for j in y(i).first .. y(i).last loop
dbms_output.put_line('Y(' || i || ')(' || j || ') = ' || y(i)(j));
end loop;
end loop;
end;
the result:
Y(1)(1) = 2
Y(1)(2) = 3
Y(2)(1) = 3
Y(2)(2) = 4

Response time of the query is too high in oracle 11g

SELECT /*+first_rows */ PPS_ID,TOTAL_WEIGHT from
(SELECT PPS_ID,TOTAL_WEIGHT ,row_number() over (order by total_weight desc) row_num
FROM (SELECT pps_id,round((((60 * name_pct_match / 100) + prs_weight + year_weight + dt_weight +
case
when mother_name_pct_match = -1
then
0
else
(10 * mother_name_pct_match / 100)
end)/decode(mother_name_pct_match,-1,(total_attrib_weight - mother_weight),total_attrib_weight)) * 100) total_weight
FROM (SELECT pps_id,
round(func_compare_name('MUHAMMAD YASIN MUHAMMAD ASHRAF',upper(name_en),' ',60)) name_pct_match,
decode(prs_nationality_id, 271, 15, 0) prs_weight,
case
when upper(mother_name_en) in ('MR','MRS','MISS','NISA','M','X')
then -1
else
round(func_compare_name(upper('.'), upper(mother_name_en), ' ',60))
end mother_name_pct_match, 10 mother_weight,
100 total_attrib_weight,
case when to_number(to_char(birth_date, 'yyyy')) = 2007 then 5 else 0 end year_weight,
case when to_char(to_date('01/01/2007','DD-MM-RRRR'), 'dd') = to_char(birth_date, 'dd')
and to_char(to_date('01/01/07','DD-MM-RRRR'), 'mm') = to_char(birth_date, 'mm') then 10
when to_date('01/01/2007','DD-MM-RRRR') between birth_date-6 and birth_date+6 then 8
when to_date('01/01/2007','DD-MM-RRRR') between birth_date-28 and birth_date+28 then 5
when to_date('01/01/2007','DD-MM-RRRR') between birth_date-90 and birth_date+90 then 3
else 0
end dt_weight
FROM INDIV_PROF_sub_test123
WHERE birth_date = '01/01/2007'
AND IS_ACTIVE = 1
AND gender_id = 1
AND round(func_compare_name('MUHAMMAD YASIN MUHAMMAD ASHRAF',upper(name_en),' ',60)) > 20
)
)
WHERE TOTAL_WEIGHT >= 70
)
where row_num <= 10
CREATE OR REPLACE FUNCTION VISION_APP.func_compare_name(p_name_str IN VARCHAR2,
p_str IN VARCHAR2,
p_delim IN VARCHAR2,
p_relev_thresh IN NUMBER)
RETURN NUMBER DETERMINISTIC AS
l_str LONG;
l_n NUMBER;
TYPE mytabletype IS TABLE OF VARCHAR2(255);
l_name_data mytabletype := mytabletype();
l_data mytabletype := mytabletype();
v_name_cnt NUMBER := 0;
v_pct_per_name NUMBER := 0;
v_pct_match NUMBER := 0;
v_flag NUMBER;
v_jaro_pct NUMBER := 0;
v_highest_jaro_pct NUMBER := 0;
v_match_exact NUMBER := 0;
v_match_exact_res NUMBER := 0;
BEGIN
l_str := p_name_str || p_delim;
LOOP
l_n := instr(l_str, p_delim);
EXIT WHEN(nvl(l_n, 0) = 0);
-- condition to check if only space
IF l_n <> 1 THEN
l_name_data.extend;
l_name_data(l_name_data.count) := ltrim(rtrim(substr(l_str,
1,
l_n - 1)));
v_name_cnt := v_name_cnt + 1;
END IF;
l_str := substr(l_str, l_n + length(p_delim));
END LOOP;
v_pct_per_name := 100 / v_name_cnt;
l_str := p_str || p_delim;
LOOP
l_n := instr(l_str, p_delim);
EXIT WHEN(nvl(l_n, 0) = 0);
l_data.extend;
l_data(l_data.count) := ltrim(rtrim(substr(l_str, 1, l_n - 1)));
l_str := substr(l_str, l_n + length(p_delim));
END LOOP;
FOR nme IN 1 .. l_name_data.count LOOP
v_flag := 0;
v_highest_jaro_pct := 0;
FOR i IN 1 .. l_data.count LOOP
v_jaro_pct := utl_match.jaro_winkler_similarity(l_name_data(nme),
l_data(i));
IF soundex(l_name_data(nme)) = soundex(l_data(i)) AND
v_jaro_pct >= p_relev_thresh THEN
IF v_jaro_pct > v_highest_jaro_pct THEN
v_highest_jaro_pct := v_jaro_pct;
END IF;
END IF;
END LOOP;
v_pct_match := v_pct_match +
(v_pct_per_name * v_highest_jaro_pct / 100);
END LOOP;
SELECT utl_match.edit_distance_similarity(p_name_str, p_str)
INTO v_match_exact
FROM dual;
if (trunc(v_match_exact) =100 ) then
return trunc(v_pct_match, 2);
else
if( v_match_exact <> 0) then
v_match_exact_res := (5 / v_match_exact) * 100;
v_pct_match := v_pct_match - v_match_exact_res;
end if;
if v_pct_match >20 then
RETURN trunc(v_pct_match, 2);
end if;
end if;
END;
This query is fetching result from INDIV_PROF_sub_test123 table this is having data of 35 million and partitioned.
i found the problematic area in query func_compare_name we are using it having name similarity checking function
Adding explain plan:
Plan
SELECT STATEMENT HINT: FIRST_ROWS
Cost: 262
Bytes: 4,056
Cardinality: 104 4
VIEW VC_CLONE.
Cost: 262
Bytes: 4,056
Cardinality: 104 3
WINDOW SORT PUSHED RANK
Cost: 262
Bytes: 5,512
Cardinality: 104 2
TABLE ACCESS BY GLOBAL INDEX ROWID TABLE VC_CLONE.INDIV_PROF_ONE_MONTH_1
Cost: 261
Bytes: 5,512
Cardinality: 104
Partition #: 3
Partitions accessed #1672 1
INDEX RANGE SCAN INDEX VC_CLONE.IDX_BIRTH_DT_INVID
Cost: 4
Cardinality: 1 –

confused between dbms_output.put_line and dbms_output.put pl/sql

i was trying to make something like this
when input : 5
it will print
A B C D E
input : 10
print
A B C D E
J I H G F
input : 15
print
A B C D E
J I H G F
K L M N O
input : 20
A B C D E
J I H G F
K L M N O
T S R Q P
and so on...
here is my code i create
declare
angka number := '&Angka';
i number := trunc(angka/5);
p number := 65;
a number := 1;
b number := 1;
begin
while a <= b loop
if mod(i,2) = 1 then
a := 5;
for b in 1..5 loop
p := p + a
dbms_output.put( chr(p) || ' ' );
a := a - 1;
end loop;
p := p + 5;
else
a := 1;
for b in 1..5 loop
p := p + a
dbms_output.put( chr(p) || ' ' );
a := a + 1;
end loop;
end loop;
dbms_output.put_line(' ');
end;
/
but i was still confused it's still didn't work
and about dbms_output.put_line vs dbms_output.put can someone explain this ? because i was trying print using dbms_output.put it's didn't show.. i don't know why
Thanks
Firstly, the line p := p + a has not been terminated by semi-colon. Ideally, the PL/SQL anonymous block shouldn't compile at first place.
Secondly, with PUT procedure, you haven't completed the line yet. It needs GET_LINES to retrieve an array of lines from the buffer.
There was a similar question, Is dbms_output.put() being buffered differently from dbms_output.put_line()?
You have some problems in your code. I don't believe that you can execute exactly this code. Propably, you forgot to copy some parts of it.
First of all, syntax errors:
declare
angka number := '&Angka';
i number := trunc(angka/5);
p number := 65;
a number := 1;
b number := 1;
begin
while a <= b loop
if mod(i,2) = 1 then
a := 5;
for b in 1..5 loop
p := p + a -- ";" missed
dbms_output.put( chr(p) || ' ' );
a := a - 1;
end loop;
p := p + 5;
else
a := 1;
for b in 1..5 loop
p := p + a -- ";" missed
dbms_output.put( chr(p) || ' ' );
a := a + 1;
end loop;
-- here you missed "end if"
end loop;
dbms_output.put_line(' ');
end;
/
Also you don't need your outer loop ("while a <= b loop"), because its condition always is true and code execution will never ends. And last - when you declare
for b in 1..5 loop
oracle creates here new variable with name "b", and inside the loop previously declared b is not visible. Try to execute this:
declare
b number := 111;
begin
for b in 1..5 loop
dbms_output.put_line(b);
end loop;
dbms_output.put_line(b);
end;
/
You will get:
1
2
3
4
5
111
If you correct these errors, your code will work as you want.

PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: begin function pragma procedure

i know the same answer is asked before, but i'm just staring blind on my code.
what's wrong with my function???
other posts say it's missing a ; but i just can't find it.
FUNCTION checkIBAN
( p_IBAN in varchar2 )
RETURN varchar2
is
v_landcode varchar2(2);
v_lengte number(2);
v_omgezettelandcode varchar2;
v_teller number(2) DEFAULT 1;
n number(9);
d varchar2;
BEGIN
v_landcode := SUBSTRING(p_IBAN, 1, 2);
select lengte
into v_lengte
from IBAN
where code = v_landcode;
if p_IBAN.LENGTH != v_lengte
then return 'F';
end if;
v_omgezettelandcode := SUBSTRING(p_IBAN, 5) || SUBSTRING(p_IBAN, 1, 4);
WHILE v_teller < v_omgezettelandcode.LENGTH LOOP
select getal
into SUBSTRING(v_omgezettelandcode, v_lengte, v_lengte)
from abc
where SUBSTRING(v_omgezettelandcode, v_lengte, v_lengte) = letter;
v_teller := v_teller + 1;
END LOOP;
d := v_omgezettelandcode;
n := SUBSTRING(d, 1, 9);
d := SUBSTRING(d, 10);
n := n/97;
WHILE d.LENGTH > 7 LOOP
n := n || SUBSTRING(d, 1, 7);
d := SUBSTRING(d, 8);
n := n/97;
END LOOP;
n := n || d;
if n/97 = 1
then return 'T';
else return 'F';
end if;
END checkIBAN;
SUBSTRING is not a function in Oracle - you're looking for SUBSTR.
A variable such as d cannot be declared as VARCHAR2 - it must be given a length. Note that this is different from a parameter, such as p_IBAN, or a return value declaration - in both cases a length is not required (or even allowed).
#wweicker correctly points out that you cannot SELECT into a SUBSTR, and must instead use a variable.
When these errors are corrected I think your function should look something like:
CREATE OR REPLACE FUNCTION checkIBAN
(p_IBAN in varchar2)
RETURN varchar2
is
v_landcode varchar2(2);
v_lengte number(2);
v_omgezettelandcode varchar2(32767); -- max possible size for a VARCHAR2 var
v_teller number(2) DEFAULT 1;
n number(9);
d varchar2(32767);
s VARCHAR2(32767);
BEGIN
v_landcode := SUBSTR(p_IBAN, 1, 2);
select lengte
into v_lengte
from IBAN
where code = v_landcode;
if p_IBAN.LENGTH != v_lengte then
return 'F';
end if;
v_omgezettelandcode := SUBSTR(p_IBAN, 5) || SUBSTR(p_IBAN, 1, 4);
WHILE v_teller < v_omgezettelandcode.LENGTH LOOP
select getal
into s
from abc
where SUBSTR(v_omgezettelandcode, v_lengte, v_lengte) = letter;
v_omgezettelandcode := SUBSTR(vomgezettelandcode, 1, v_lengte-1) ||
letter ||
SUBSTR(vomgezettelandcode, v_lengte+LENGTH(letter));
v_teller := v_teller + 1;
END LOOP;
d := v_omgezettelandcode;
n := SUBSTR(d, 1, 9);
d := SUBSTR(d, 10);
n := n/97;
WHILE d.LENGTH > 7 LOOP
n := n || SUBSTR(d, 1, 7);
d := SUBSTR(d, 8);
n := n/97;
END LOOP;
n := n || d;
if n/97 = 1
then return 'T';
else return 'F';
end if;
END checkIBAN;
Best of luck.
Share and enjoy.
You need to use CREATE OR REPLACE FUNCTION instead of just FUNCTION
ex.
CREATE OR REPLACE FUNCTION checkIBAN
( p_IBAN in varchar2 )
RETURN varchar2
is
v_landcode varchar2(2);
v_lengte number(2);
v_omgezettelandcode varchar2;
v_teller number(2) DEFAULT 1;
n number(9);
d varchar2;
BEGIN
v_landcode := SUBSTRING(p_IBAN, 1, 2);
select lengte
into v_lengte
from IBAN
where code = v_landcode;
if p_IBAN.LENGTH != v_lengte
then return 'F';
end if;
v_omgezettelandcode := SUBSTRING(p_IBAN, 5) || SUBSTRING(p_IBAN, 1, 4);
WHILE v_teller < v_omgezettelandcode.LENGTH LOOP
select getal
into SUBSTRING(v_omgezettelandcode, v_lengte, v_lengte)
from abc
where SUBSTRING(v_omgezettelandcode, v_lengte, v_lengte) = letter;
v_teller := v_teller + 1;
END LOOP;
d := v_omgezettelandcode;
n := SUBSTRING(d, 1, 9);
d := SUBSTRING(d, 10);
n := n/97;
WHILE d.LENGTH > 7 LOOP
n := n || SUBSTRING(d, 1, 7);
d := SUBSTRING(d, 8);
n := n/97;
END LOOP;
n := n || d;
if n/97 = 1
then return 'T';
else return 'F';
end if;
END checkIBAN;
There is another error as well. Where you have:
select getal
into SUBSTRING(v_omgezettelandcode, v_lengte, v_lengte)
from abc
where SUBSTRING(v_omgezettelandcode, v_lengte, v_lengte) = letter;
You use INTO you must specify a variable. You can't specify the built in function 'SUBSTRING' to "select into"
ex.
select getal
into SOME_LOCAL_VARIABLE_NAME
from abc
where SUBSTRING(v_omgezettelandcode, v_lengte, v_lengte) = letter;
thank you all, eventually i turned it over al little bit, now it works.
CREATE OR REPLACE FUNCTION checkIBAN
(p_IBAN in varchar2)
RETURN varchar2
is
v_landcode varchar2(2);
v_lengte number(2);
v_omgezettelandcode varchar2(32767); -- max possible size for a VARCHAR2 var
v_teller number(2) DEFAULT 1;
n number(9);
d varchar2(32767);
s VARCHAR2(32767);
v_omgezet varchar2(32767);
v_number varchar2(32767);
BEGIN
v_landcode := SUBSTR(p_IBAN, 1, 2);
select lengte
into v_lengte
from IBAN
where code = v_landcode;
if LENGTH(p_IBAN) != v_lengte then
return 'F';
end if;
v_omgezettelandcode := SUBSTR(p_IBAN, 5) || SUBSTR(p_IBAN, 1, 4);
while v_teller < LENGTH(v_omgezettelandcode) LOOP
if SUBSTR(v_omgezettelandcode, v_teller, v_teller) in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
then v_omgezet := v_omgezet || SUBSTR(v_omgezettelandcode, v_teller, v_teller);
else
select getal
into v_number
from abc
where letter = SUBSTR(v_omgezettelandcode, v_teller, v_teller);
v_omgezet := v_omgezet || v_number;
end if;
end loop;
d := v_omgezet;
n := SUBSTR(d, 1, 9);
d := SUBSTR(d, 10);
n := n/97;
WHILE LENGTH(d) > 7 LOOP
n := n || SUBSTR(d, 1, 7);
d := SUBSTR(d, 8);
n := n/97;
END LOOP;
n := n || d;
if n/97 = 1
then return 'T';
else return 'F';
end if;
END checkIBAN;
Another potential solution for those using DbVisualizer, (and maybe other tools?). This is what solved this problem for me.
Add these two lines to your code, like so:
--/
(all your code)
/

Resources