Custom SQL function - PL/SQL: Statement ignored - sql

Hi made a function that modifies a little bit the INSTR function (Oracle SQL):
instead of getting '0' when a space char isn't found, I get the length of the string.
It compiles but when I try to execute it, i'm getting the ORA-06550 error (which is, if i'm not wrong, a compilation error).
I tried this function as a procedure and it runs all right... so I don't understand why it doesn't want to execute.
Can you help me?
CREATE OR REPLACE FUNCTION "INSTR2" (str varchar2) RETURN NUMBER AS
pos number(4,0) := 0;
BEGIN
select INSTR(str, ' ') into pos from dual;
if (pos = 0) then
select to_number(length(str)) into pos from dual;
return pos;
else
return pos;
end if;
END INSTR2;
Thanks a lot,
R.L.

Well, there is already a built-in function called INSTR2 in Oracle (look, here it is).
I've just compiled your function with another name and it worked. So the code is valid, you just have to pick the name for it.
Apparently Oracle resolves INSTR2 to the built-in function despite the fact you now have the function with such name in your own schema (I couldn't find the reason for it in docs, but this behaviour is not exactly surprising). And INSTR2 expects more parameters than your implementation. That causes a runtime error.

Change you function name for excample to INSTR_SPACE and everething there will be ok, because in oracle there is a instr2 function and you will have problem during calling
Change your function body to
create or replace
function INSTR_SPACE(str varchar2) return number as
pos number(4, 0) := 0;
begin
pos := INSTR(str, ' ');
if (pos = 0) then
return to_number(length(str));
else
return pos;
end if;
end INSTR_SPACE;
you dont need sql operations, you can do it by simple pl/sql operations and it will be more faster

Related

PLS-00103 Encountered the symbol "BEGIN"

This may be a repeat question but I'm very new with pl sql so I'm going to ask it anyways. I wrote a function that is supposed to determine if a varchar2 contains all alpha characters. It is defined as...
CREATE OR REPLACE FUNCTION isAlpha (al IN VARCHAR2) RETURN CHAR;
BEGIN
FOR i in 1..LENGTH(al) LOOP
IF ASCII(SUBSTR(al, i, 1)) < 65 OR ASCII(SUBSTR(al, i, 1)) > 90
THEN RETURN 'F';
END IF;
END LOOP;
RETURN 'T';
END isAlpha;
I am receiving the error Error(1,1): PLS-00103: Encountered the symbol "BEGIN" and I have no clue what it's getting at. I've tried debugging it for a decent amount of time with no luck. Thanks for any responses.
Your syntax is slightly off - get rid of the ; after the RETURN clause, and add an AS:
CREATE OR REPLACE FUNCTION isAlpha (al IN VARCHAR2) RETURN CHAR AS
BEGIN
...
See the Oracle documentation for further information
Hi in head "CREATE OR REPLACE FUNCTION isAlpha (al IN VARCHAR2) RETURN CHAR;" replaces ";" by IS.

Assigning a string value to a variable of type NUMBER in pl/sql procedure not throwing any error

I have started working on pl/sql recently. So still not very clear with the concepts. I am a writing a Stored procedure which has some input values.
using thses input values as keys,i create a cursor.
After this i iterate through the cursor output , and call insert statement for each row fetched.
before calling the insert, i am doing few data manipulations.
Splitting a String '4564:0:75556' considering : as the delimiter.
For this i am using SUBSTR and INSTR functions
My actual question starts here.
The output of SUBSTR will be a string value. i am assigning this value to a variable of type NUMBER which i declared in the proc.
I was expecting an error while compiling this proc or atleast when i test it.
Strangely i didnt get any error, the proc works fine.
is this the expected behaviour?
Can we assign a string value to variable of type NUMBER?
in my proc i am assignin output of SUBSTR to variables d_c1_subscr_no, d_c1_account_no, d_c1_subscr_no_resets NUMBER
My Stored proc:
CREATE OR REPLACE PROCEDURE P4_UPDATE_BILL_PERIOD_BULK(oldperiod IN VARCHAR,
newperiod IN VARCHAR,
accountno IN VARCHAR) IS
d_c1_subscr_no NUMBER;
d_c1_account_no NUMBER;
d_c1_subscr_no_resets NUMBER;
d_first_occ NUMBER;
d_second_occ NUMBER;
CURSOR c1_active_subs IS
select ciem.external_id as occ_ext_id,
ciem.subscr_no as fx_subscr_no,
ciem.subscr_no_resets as fx_subscr_no_resets
from customer_id_equip_map ciem, service s
where ciem.subscr_no = s.subscr_no
AND s.parent_account_no = to_number(accountno)
AND ciem.subscr_no_resets = s.subscr_no_resets
AND ciem.external_id_type = 6
AND ciem.active_date < SYSDATE
AND (ciem.inactive_date is null or ciem.inactive_date > SYSDATE);
d_subscriber c1_active_subs%ROWTYPE;
BEGIN
OPEN c1_active_subs;
LOOP
FETCH c1_active_subs
into d_subscriber;
EXIT WHEN c1_active_subs%NOTFOUND;
IF c1_active_subs%FOUND THEN
d_first_occ := INSTR(d_subscriber.occ_ext_id, ':', 1, 1);
d_second_occ := INSTR(d_subscriber.occ_ext_id, ':', 1, 2);
d_c1_subscr_no := SUBSTR(d_subscriber.occ_ext_id,
1,
d_first_occ - 1);
d_c1_subscr_no_resets := SUBSTR(d_subscriber.occ_ext_id,
d_first_occ + 1,
d_second_occ - d_first_occ - 1);
d_c1_account_no := SUBSTR(d_subscriber.occ_ext_id,
d_second_occ + 1);
INSERT INTO P4_BULK_DATA
(BATCH_ID, STATUS, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8)
VALUES
(10300,
0,
accountno,
d_subscriber.fx_subscr_no,
d_subscriber.fx_subscr_no_resets,
d_c1_account_no,
d_c1_subscr_no,
d_c1_subscr_no_resets,
oldperiod,
newperiod);
END IF;
END LOOP;
CLOSE c1_active_subs;
END;
Oracle database will normally conduct implicit conversions between many data types. As clarified in the link provided in the comment, Oracle implicitly converts from VARCHAR2 to NUMBER and vise versa. That said, it is always not recommended approach to rely on Oracle implicit conversions. It is always better to use the rich library of conversion functions provided by Oracle. For example:
Using the concatenation operator (||) to concatenate a string and an arithmetic expression can produce an error, which you can prevent by using the TO_CHAR function to convert the arithmetic expression to a string before concatenation
Relying on language settings in the database for the format of a DATE value can produce unexpected results, which you can prevent by using the TO_CHAR function and specifying the format that you want

Error- ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW conversion

I am attempting to read a BLOB message and display it as a variable in one of my procedures, but am getting the error below:
Error - ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW
conversion (actual: 9923, maximum: 2000)
I have googled and found a suggestion to trim the BLOB message as below, but I would rather display the complete BLOB message as a string.
UTL_RAW.CAST_TO_VARCHAR2(dbms_lob.substr(variable_name,2000,1))
How can I display the complete message? Is there a setting on either the database or procedure level that I can change?
I got this worked by using the option described in
http://www.dba-oracle.com/t_convert_blob_varchar_datatype.htm
Try to use DBMS_LOB.GETLENGTH(), instead of trimming the string
You can get around the buffer issue by reading the BLOB value in chunks. In order to do that, you can define a user defined function (UDF) as suggested here. The following UDF reads the BLOB field one chunk at a time, converts that to VARCHAR2 and appends the results consecutively to return the result as a CLOB:
CREATE OR REPLACE FUNCTION VC2CLOB_FROM_BLOB(B BLOB)
RETURN CLOB IS
c CLOB;
n NUMBER;
BEGIN
IF (b IS NULL) THEN
RETURN NULL;
END IF;
IF (LENGTH(b) = 0) THEN
RETURN EMPTY_CLOB();
END IF;
DBMS_LOB.CREATETEMPORARY(c, TRUE);
n := 1;
WHILE (n + 32767 <= LENGTH(b)) LOOP
DBMS_LOB.WRITEAPPEND(c, 32767, UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(b, 32767, n)));
n := n + 32767;
END LOOP;
DBMS_LOB.WRITEAPPEND(c, LENGTH(b) - n + 1, UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(b, LENGTH(b) - n + 1, n)));
RETURN c;
END;
/
After having defined it, you can simply call it like so:
SELECT VC2CLOB_FROM_BLOB(variable_name);
Worked like a charm for my problem.

SQL: How to get substring from function output in sql?

IN one of My Application. We have one query, where actully we are calling a function and function returns o/p as String. Any one have idea how to get substring from function returned o/p?
I am using like this
select substr(myfunction(),0,4000) from dual.
I am getting below issue.
ORA-06502: PL/SQL: numeric or value error: character string buffer too
small.
Please help me . Thanks in Advance.
Since you're applying a substr, presumably the value being returned by your function is greater than 4000 characters. If that's the case then you will get this error from SQL, you can't avoid it. It's trying to assign the long string value to an (implicit) SQL-level varchar2, which of course cannot be more than 4000 characters either, before passing that to the substr function.
You will have to add the substr to the return from your function, or if it is sometimes called from somewhere that can handle the long values, you can have a wrapper function that only returns the first 4000 characters - so you can have the appropriate value as needed.
To demonstrate with a dummy function to (inefficiently!) create a large string:
create or replace function myfunction(strlen number) return varchar2 is
str varchar2(32767) := 'X';
begin
while length(str) < least(strlen, 32767) loop
str := str || 'X';
end loop;
return str;
end myfunction;
/
This is fine because the function's output doesn't exceed the SQL varchar2 size:
select length(substr(myfunction(4000),0,4000)) from dual;
LENGTH(SUBSTR(MYFUNCTION(4000),0,4000))
---------------------------------------
4000
But this gets your error because the function's output is too long:
select length(substr(myfunction(4001),0,4000)) from dual;
SQL Error: ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "STACKOVERFLOW.MYFUNCTION", line 7
06502. 00000 - "PL/SQL: numeric or value error%s"
With a simple wrapper function as a workaround:
create or replace function trunc_myfunction(strlen number) return varchar2 is
begin
return substr(myfunction(strlen), 0, 4000);
end;
/
select length(substr(trunc_myfunction(4000),0,4000)) from dual;
LENGTH(SUBSTR(TRUNC_MYFUNCTION(4000),0,4000))
---------------------------------------------
4000
select length(substr(trunc_myfunction(4001),0,4000)) from dual;
LENGTH(SUBSTR(TRUNC_MYFUNCTION(4001),0,4000))
---------------------------------------------
4000
select length(substr(trunc_myfunction(32767),0,4000)) from dual;
LENGTH(SUBSTR(TRUNC_MYFUNCTION(32767),0,4000))
----------------------------------------------
4000
Most probably you are trying to store more characters than is allowed in one of the variables that you use in your function. See: PL/SQL: numeric or value error: character string buffer too small %ROWTYPE
Simplest example:
DECLARE
v_varchar2_test VARCHAR2(5);
BEGIN
v_varchar2_test := '123456';
END;
And the error is, like in your case, ORA-06502.
Make sure that the value returned by the function is of the correct type;
I have just tried it like this:
create or replace
FUNCTION MONTH
(DATA IN DATE)
RETURN VARCHAR IS
BEGIN
RETURN TO_CHAR(DATA, 'MM');
END;
and the call:
SELECT substr(MONTH(SYSDATE),0,1) FROM DUAL;
and it worked.

Oracle insert() function like mysql's

Does oracle have an equivalent function like mysql's Insert() to handle strings ?
EDIT:
This is the coded answer in order to be easily understood
create or replace function fn_insert(ori_string in varchar2, in_pos in number,
p_length in number, new_string in varchar2)
return varchar2
is
resul varchar2(250) default '';
begin
if in_pos < 0 then
resul := ori_string;
else
resul := substr(ori_string, 1, in_pos-1)||new_string||substr(ori_string, in_pos+p_length, length(ori_string) - ((in_pos+p_length)-1));
end if;
return resul;
END fn_insert;
/
You can do it manually. So, insert(ori_string, in_pos, length, new_string) could be written as:
substr(ori_string, 1, in_pos)||new_string||substr(orig_string, in_pos+length, length(orig_string) - (in_pos+length))
In other databases, this function is also called stuff()