PLS-00103 Encountered the symbol "BEGIN" - sql

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.

Related

Simple word replacement in output from SQL

I'm running PostgreSQL 9.4.
Is there a replace string function which can take an array of words, or other similar function?
Ex.
SELECT REPLACE(my_column, ['blue', 'red'], ['ColorBlue', 'ColorRed']);
So blue becomes ColorBlue, and red becomes ColorRed?
It's not only such simple replacements, but for the example I'm using this.
One way is create it:
create or replace function rep_arr(str text, src text[], rep text[])
returns text as $$
begin
for i in 1..array_length(src, 1) loop
str := replace(str, src[i], rep[i]);
end loop;
return str;
end; $$ language plpgsql
Call:
select rep_arr('bla bla blue bla red bla', '{blue,red}' , '{ColorBlue,ColorRed}');
I agree with #OtoShavadze that you can write your own function.
Here is my solution:
I use generate_subscripts(array anyarray, dim int) function as suggested in Searching in Arrays documentation.
CREATE OR REPLACE FUNCTION translate(string text, from_array text[], to_array text[])
RETURNS text AS
$BODY$
DECLARE
output text;
BEGIN
SELECT INTO output
to_array[idx]
FROM
generate_subscripts(from_array, 1) AS idx
WHERE
from_array[idx] = string; -- here you can change the search condition
IF FOUND THEN
RETURN output;
ELSE
RETURN string;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
It finds and replaces whole words but you can change it (line marked in the code) to find only a substring, match case-insensitive, etc...
You should also add parameter checking: arrays should not be null, multidimensional nor differ in size:
IF from_array IS NULL OR to_array IS NULL THEN
RAISE EXCEPTION 'NULL parameters';
END IF;
IF array_ndims(from_array) != 1 OR array_ndims(to_array) != 1 THEN
RAISE EXCEPTION 'Multidimensional parameters';
END IF;
IF array_length(from_array, 1) != array_length(to_array, 1) THEN
RAISE EXCEPTION 'Parameters size differ';
END IF;
SELECT translate('red', ARRAY['blue', 'red'], ARRAY['ColorBlue', 'ColorRed']);
returns
ColorRed

Custom SQL function - PL/SQL: Statement ignored

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

How to cut varchar/text before n'th occurence of delimiter? PostgreSQL

I have strings (saved in database as varchar) and I have to cut them just before n'th occurence of delimiter.
Example input:
String: 'My-Example-Awesome-String'
Delimiter: '-'
Occurence: 2
Output:
My-Example
I implemented this function for fast prototype:
CREATE OR REPLACE FUNCTION find_position_delimiter(fulltext varchar, delimiter varchar, occurence integer)
RETURNS varchar AS
$BODY$
DECLARE
result varchar = '';
arr text[] = regexp_split_to_array( fulltext, delimiter);
word text;
counter integer := 0;
BEGIN
FOREACH word IN ARRAY arr LOOP
EXIT WHEN ( counter = occurence );
IF (counter > 0) THEN result := result || delimiter;
END IF;
result := result || word;
counter := counter + 1;
END LOOP;
RETURN result;
END;
$BODY$
LANGUAGE 'plpgsql' IMMUTABLE;
SELECT find_position_delimiter('My-Example-Awesome-String', '-', 2);
For now it assumes that string is not empty (provided by query where I will call function) and delimiter string contains at least one delimiter of provided pattern.
But now I need something better for performance test. If it is possible, I would love to see the most universal solution, because not every user of my system is working on PostgreSQL database (few of them prefer Oracle, MySQL or SQLite), but it is not the most importatnt. But performance is - because on specific search, that function can be called even few hundreds times.
I didn't find anything about fast and easy using varchar as a table of chars and checking for occurences of delimiter (I could remember position of occurences and then create substring from first char to n'th delimiter position-1). Any ideas? Are smarter solutions?
# EDIT: yea, I know that function in every database will be a bit different, but body of function can be very similliar or the same. Generality is not a main goal :) And sorry for that bad function working-name, I just saw it has not right meaning.
you can try doing something based on this:
select
varcharColumnName,
INSTR(varcharColumnName,'-',1,2),
case when INSTR(varcharColumnName,'-',1,2) <> 0
THEN SUBSTR(varcharColumnName, 1, INSTR(varcharColumnName,'-',1,2) - 1)
else '...'
end
from tableName;
of course, you have to handle "else" the way you want. It works on postgres and oracle (tested), it should work on other dbms's because these are standard sql functions
//edit - as a function, however this way it's rather hard to make it cross-dbms
CREATE OR REPLACE FUNCTION find_position_delimiter(fulltext varchar, delimiter varchar, occurence integer)
RETURNS varchar as
$BODY$
DECLARE
result varchar := '';
delimiterPos integer := 0;
BEGIN
delimiterPos := INSTR(fulltext,delimiter,1,occurence);
result := SUBSTR(fulltext, 1, delimiterPos - 1);
RETURN result;
END;
$BODY$
LANGUAGE 'plpgsql' IMMUTABLE;
SELECT find_position_delimiter('My-Example-Awesome-String', '-', 2);
create or replace function trunc(string text, delimiter char, occurence int) returns text as $$
return delimiter.join(string.split(delimiter)[:occurence])
$$ language plpythonu;
# select trunc('My-Example-Awesome-String', '-', 2);
trunc
------------
My-Example
(1 row)

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()