I am trying to write a script that prompts for a input and it should validate if the given input has 19 characters;the first 3 characters must be 'ABC' followed by 16 characters(combination of alphabets and numbers)...
def mch_id='&1'
declare
chk_var varchar2(200) := '&mch_id';
begin
IF chk_var like'ABC_____________' then
dbms_output.put_line('correct');
else
dbms_output.put_line('incorrect');
end if;
end;
Expected Output :
ABC5678GVTC438755RW43 - correct
ADSE4NJ8GGFT5FVNOKNHY - incorrect
Your comparison string is only 16 characters long, ABC and 13 underscores. You need 16 underscores to follow ABC according to your specification.
EDIT: As HepC notes below, even after fixing the number of underscores, you may still get incorrect answers. This is because the underscore stands for ANY character, not only for alpha or numeric.
Try this instead:
... if regexp_like(chk_var, '^ABC[[:alnum:]]{16}$') then...
This evaluates as TRUE if and only if chk_var matches
from the beginning of the string (the ^ marker)
the letters A, B, C in order
any alpha or numeric character (the outer [...] means any single character in the list provided within [...]; inside it, [:alnum:] is shorthand for any alpha or numeric character)
exactly 16 occurrences of "a single alnum character" (the 16 characters may be different from each other) (the {16} marker)
and the end of the string right after that (the $ marker).
Sample SQL*Plus session (screenshot):
SQL> set serveroutput on
SQL> define mch_id = 'ABC1234567812345678'
SQL> declare
2 chk_var varchar2(200) := '&mch_id';
3 begin
4 if regexp_like(chk_var, '^ABC[[:alnum:]]{16}$') then
5 dbms_output.put_line('correct');
6 else
7 dbms_output.put_line('incorrect');
8 end if;
9 end;
10 /
old 2: chk_var varchar2(200) := '&mch_id';
new 2: chk_var varchar2(200) := 'ABC1234567812345678';
correct
PL/SQL procedure successfully completed.
SQL> define mch_id = 'ABC123456781234%%%%'
SQL> /
old 2: chk_var varchar2(200) := '&mch_id';
new 2: chk_var varchar2(200) := 'ABC123456781234%%%%';
incorrect
PL/SQL procedure successfully completed.
Related
I have a procedure in which I'm trying to write a source code (1290 lines) to dbms_output like this:
dbms_output.put_line(DBMS_METADATA.GET_DDL('FUNCTION', 'name', 'owner')); --MYPROC, line 6
I'm getting :
ORA-06502: PL/SQL: numeric or value error
ORA-06512: in "MYPROC", line 6
.
This error occures in toad.
I can execute in editor tab of toad:
SELECT DBMS_METADATA.GET_DDL('FUNCTION', 'name', 'owner') FROM DUAL;
I mean I'm getting the source code in 'Data grid'.
Same happens when I try to store the code in a CLOB variable:
src CLOB;
...
src := DBMS_METADATA.GET_DDL('FUNCTION', 'name', 'owner') ; --MYPROC, line 6
Any clue?
From the documentation for dbms_output:
The maximum line size is 32767 bytes.
That means that you can't pass more than that in a single put_line call. You are currently passing your whole CLOB, which at 1290 lines is likely to exceed that limit. And the error you get when you do that is "ORA-06502: PL/SQL: numeric or value error", as you are seeing.
You can split your CLOB into smaller chunks, and as it is already multiple lines it makes sense to make each chunk a single line from the DDL. You can do that by looking for newline characters, extracting all the text up to the next one, and printing that. You need a few variables to keep track of where you are. Something like this should work for you:
declare
src clob;
src_length pls_integer;
pos pls_integer := 1;
buffer varchar2(32767);
amount pls_integer := 32767;
begin
src := dbms_metadata.get_ddl('FUNCTION', 'TEST_FUNCTION_1', user);
src_length := dbms_lob.getlength(src);
while pos < src_length loop
-- read to next newline if there is one, rest of CLOB if not
if dbms_lob.instr(src, chr(10), pos) > 0 then
-- see how many charcaters there are until next newline
amount := dbms_lob.instr(src, chr(10), pos) - pos;
-- if there are any, read them into the buffer; otherwise clear it
if amount > 0 then
dbms_lob.read(src, amount, pos, buffer);
else
buffer := null;
end if;
pos := pos + amount + 1; -- skip newline character
else
-- no newline so read everything that is left
amount := 32767;
dbms_lob.read(src, amount, pos, buffer);
pos := pos + amount;
end if;
dbms_output.put_line(buffer);
end loop;
end;
/
It won't work if you have a single line (without or without a newline at the end) that is more than 32k, which hopefully won't be an issue with DDL. (You could sort of handle it, but doing so would inject additional newlines, which wouldn't be good either.)
What you are saying can't be true. DBMS_OUTPUT.PUT_LINE can't be used at SQL level, it belongs to PL/SQL.
What is MYPROC and what does it contain at line #6?
Which "editor" is "I can execute in editor"?
Numeric or value error is usually related to the fact that you're trying to store "large" values into a "small" variable:
SQL> declare
2 l_var varchar2(2);
3 begin
4 l_var := 'ABC';
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 4
SQL>
which is what - I presume - you did.
Another cause is wrongly declared variable, e.g.
SQL> declare
2 l_var number;
3 begin
4 l_var := 'A';
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 4
SQL>
I'll try to guess what you might be doing:
SQL> set serveroutput on
SQL> DECLARE
2 src CLOB;
3 BEGIN
4 src := DBMS_METADATA.GET_DDL ('PACKAGE', 'MY_PKG', 'SCOTT');
5 DBMS_OUTPUT.put_line ('len = ' || DBMS_LOB.getlength (src));
6 END;
7 /
len = 67239
PL/SQL procedure successfully completed.
SQL>
As you can see, it works OK for me. Package isn't that small (see its length), so - can't really tell what you did wrong. I'd suggest you to do exactly as I did - copy/paste code I posted above (those 7 lines), fix information (function, its name, owner) and post the result by editing the original question, not as a comment.
I've a string with the values - 'a','b','c','d,'e'. I need to convert each of the values to the text null - null,null,null,null,null. If there are 10 values in quotes and separated by comma, then 10 null will appear. I tried using REGEXP_REPLACE but failed to get the result.
declare
a varchar2(32767) := q'#'a','b','c'#';
c varchar2(32767);
begin
c := replace(REGEXP_REPLACE (a, <don't know what pattern should be here>, 'null'),'''');
dbms_output.put_line(c);
end;
/
There are many ways to do this. For example, you could use the regular expression '[^,]+' - which means any number (one or more) of consecutive non-comma characters. Then every occurrence of that pattern will be replaced with the replacement string (while the commas will stay in place).
declare
a varchar2(32767) := q'#'a','b','c'#';
c varchar2(32767);
begin
c := REGEXP_REPLACE (a, '[^,]+', 'null'); -- notice the regular expression
dbms_output.put_line(c);
end;
/
null,null,null
PL/SQL procedure successfully completed.
I have a varchar2 field and want to split it to array of chars
Like 'ABCDEF' --> 'A' 'B' 'C' 'D' 'E'
How can i convert my Field Values to chars array?
If you actually mean a PL/SQL collection of characters, you could do something like
SQL> ed
Wrote file afiedt.buf
1 declare
2 type char_arr is table of char(1) index by pls_integer;
3 l_str varchar2(100) := 'ABCDEF';
4 l_arr char_arr;
5 begin
6 for i in 1 .. length(l_str)
7 loop
8 l_arr(i) := substr( l_str, i, 1 );
9 end loop;
10 dbms_output.put_line( l_arr.count );
11* end;
SQL> /
6
PL/SQL procedure successfully completed.
Without understanding the business requirements, though, I would tend to be very suspicious. When you find yourself breaking apart strings in PL/SQL, that almost always implies that you have stored data in a non-atomic form and need to address the data model issue.
There is somthing strange I wouls like to understand
let's say we have this code :
DECLARE
a varchar2(6);
BEGIN
a := '000001';
END;
This works good. No problem
Now we have this :
DECLARE
a varchar2(6);
BEGIN
a := TO_CHAR(1, '000000');
END;
It does not work:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
why?
A problem with nls_language maybe? what problem? what solution?
Thank you
The TO_CHAR result has a space at the beginning, making its total length 7 characters. The space is reserved for a minus sign if the number is negative. If you try this query you'll see:
SELECT '[' || TO_CHAR(1, '000000') || ']' FROM DUAL;
The result is:
[ 000001]
^ space for a minus sign
To get the result without the space, use the FM modifier:
a := TO_CHAR(1, 'FM000000');
Or, just use `LTRIM' :
SQL> set serveroutput on;
SQL> DECLARE
2 a VARCHAR2(6);
3 BEGIN
4 A := LTRIM(TO_CHAR(1, '000000'));
5 dbms_output.put_line(a);
6 END;
7 /
000001
PL/SQL procedure successfully completed.
SQL>
Note that a leading blank only appears before a positive number with no sign formatting. No leading blank appears before a negative number, or before any signed number, regardless of the placement of the sign.
The “FM” format to override the default leading blank for unsigned positive numbers
I have a table containing a column of type Number
create table tmp (
/*other fields*/
some_field Number
)
and in a PL SQL script, I want to convert that field to a varchar. However, i don't know its length, so I get an exception
Exception message is ORA-06502:
PL/SQL: numeric or value error:
character string buffer too small
v_some_field varchar(21);
/*...*/
v_some_field := TO_CHAR(some_field,'999999999999999999999');
How should i declare the v_some_field buffer? Setting it to varchar(32767) seems quite brute, is there any alternative?
you're getting an error not because the number is too large but because the result of your to_char is 22 characters long (21x"9"+one character for the sign):
SQL> DECLARE
2 some_field NUMBER := 123;
3 v_some_field VARCHAR(21);
4 BEGIN
5 v_some_field := TO_CHAR(some_field, '999999999999999999999');
6 END;
7 /
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 6
SQL> DECLARE
2 some_field NUMBER := 123;
3 v_some_field VARCHAR(22);
4 BEGIN
5 v_some_field := TO_CHAR(some_field, '999999999999999999999');
6 END;
7 /
PL/SQL procedure successfully completed
You could determine the maximum length of your converted varchar2 by converting a negative value with integral and fractional digits:
set serveroutput on
declare
n number;
begin
n := -4/3;
dbms_output.put_line(length(to_char(n)));
end;
/
Output is 41 for me.