PL SQL function problems - sql

I'm trying to write a PL SQL function however I'm having some issues with the formatting and general syntax.
This is my current code:
create or replace function getName(name IN varchar, organisation OUT varchar,
xcoord OUT number, ycoord OUT number, errormsg OUT varchar)
return varchar2
as
begin
Select name, LOCX, LOCY
from BBT_POI
WHERE (UPPER(name) LIKE UPPER('%'|| NAME || '%'));
return NAME;
end;
/
variable input varchar;
Variable errormsg varchar;
Variable organisation varchar;
Variable x NUMBER;
Variable y NUMBER;
execute getName ('yach', organisation, x, y, errormsg);
and these are the error messages when I run the create or replace function command:
FUNCTION GETNAME compiled
Errors: check compiler log
Error(5,3): PLS-00428: an INTO clause is expected in this SELECT statement
and when I run the execute line I get this:
Error starting at line : 40 in command -
execute getName ('yach', organisation, x, y, errormsg)
Error report -
ORA-06550: line 1, column 24:
PLS-00201: identifier 'ORGANISATION' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The procedure should take one IN parameter (name or part of a name), and return four OUT parameters (the name of the organisation, X-coord, Y-coord, error message(or 'none' if no error message is thrown)).
I know currently the code doesn't look for errors however I am just trying to get a simple version working which I can add more functionality to after.

There are couple of problems with your code:
First you are experiencing the PLS-00428 error which means you are not giving an INTO clause.
Example:
create or replace function getName(name IN varchar, organisation OUT varchar,
xcoord OUT number, ycoord OUT number, errormsg OUT varchar)
return varchar2
as
begin
Select name, LOCX, LOCY
INTO name, XCOORD, YCOORD -- I assume this is how you need them kept
from BBT_POI
WHERE (UPPER(name) LIKE UPPER('%'|| NAME || '%'));
return NAME;
end;
/
Next your next block must be defined as an anonymous block. Oracle doesn't know you are trying to use PL/SQL unless you specifically tell it you are.
So your variable stuff needs to be in a block (also you don't need to say variable):
DECLARE
input varchar;
errormsg varchar;
organisation varchar;
x NUMBER;
y NUMBER;
BEGIN
getName('yach', organisation, x, y, errormsg);
END;
/

I do not have a tool right now to check whether it works for sure, but try this:
create or replace function getName(p_name IN varchar, organisation OUT varchar,
xcoord OUT number, ycoord OUT number, errormsg OUT varchar)
return varchar2
as
begin
Select name, LOCX, LOCY
INTO p_name, xcoord, coord
from BBT_POI
WHERE (UPPER(p_name) LIKE UPPER('%'|| p_name || '%'));
return p_name;
end;
/
declare
input varchar;
errormsg varchar;
organisation varchar;
x NUMBER;
y NUMBER;
begin
input:=getName ('yach', organisation, x, y, errormsg);
end;

Related

Error in returning record from function in Oracle PL/SQL

DECLARE
TYPE type_supplier IS
RECORD(supp_phone supplier.supplier_phone%TYPE,
supp_status supplier.supplier_status%TYPE);
FUNCTION fn_supplier(supp_name supplier.supplier_name%TYPE)
RETURN type_supplier
IS supp type_supplier;
BEGIN
select supplier_phone, supplier_status
into supp.supp_phone, supp.supp_status
from supplier
where supplier_name = supp_name;
RETURN supp;
END;
The question is: Create a function that returns Phone Number and status for inputted supplier name. Supplier table has supplier_id, supplier_name, supplier_address, supplier_email, supplier_phone, supplier_status.
I am getting error in above code as:
Error report -
ORA-06550: line 16, column 4:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
begin function pragma procedure
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I don't know hoe to return multiple values from PL/SQL function. I'm using record type for that but getting the error.
I am open for any solution, changes or alternative methods..
Your declaration of the TYPE is not correct.
You can use the OBJECT type and use it as follows:
create TYPE type_supplier IS
OBJECT(supp_phone supplier.supplier_phone%TYPE,
supp_status supplier.supplier_status%TYPE);
/
FUNCTION fn_supplier(supp_name supplier.supplier_name%TYPE)
RETURN type_supplier
IS supp type_supplier;
BEGIN
select supplier_phone, supplier_status
into supp.supp_phone, supp.supp_status
from supplier
where supplier_name = supp_name;
RETURN supp;
END;
/
In PL/SQL what's commonly done is to return an opened cursor which the caller can then walk through. For example:
FUNCTION fn_supplier(supp_name supplier.supplier_name%TYPE)
RETURN SYS_REFCURSOR
IS
csr SYS_REFCURSOR
BEGIN
OPEN csr FOR
SELECT SUPPLIER_PHONE, SUPPLIER_STATUS
FROM SUPPLIER
WHERE SUPPLIER_NAME = pinSupplier_name;
RETURN csr;
END fn_supplier;
Then the caller of the function looks something like:
DECLARE
csrSupplier SYS_REFCURSOR;
vSupplier_phone SUPPLIER.SUPPLIER_PHONE%TYPE;
vSupplier_status SUPPLIER.SUPPLIER_STATUS%TYPE;
BEGIN -- some anonymous
csrSupplier := fn_supplier('Cthulhu, Inc.'); -- why deal with the lesser evil?
LOOP
FETCH csrSupplier INTO vSupplier_phone, vSupplier_status;
EXIT WHEN cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Phone=' || vSupplier_phone ||
' Status=' || vSupplier_status);
END LOOP;
CLOSE csrSupplier;
END;

How to fix strange oracle PL/SQL error - "PLS-00049: bad bind variable"

I am trying to write an execute an oracle PL/SQL function that return the number of records within a table, where one of the fields matches a certain name.
Here is my code:
create or replace function getNum
return number
as
v_x number;
begin
SELECT COUNT(*) INTO :v_x
FROM UserResponses WHERE NHSPlatform_Name = 'Improvement Data and Analytics';
return v_x;
end;
/
execute getNum();
I keep getting strange errors:
Function GETNUM compiled
LINE/COL ERROR
--------- ------------------------------------------------------------- 6/22 PLS-00049: bad bind variable 'V_X' Errors: check compiler log
Error starting at line : 85 in command - BEGIN getNum(); END; Error
report - ORA-06550: line 1, column 7: PLS-00905: object
B7011343.GETNUM is invalid ORA-06550: line 1, column 7: PL/SQL:
Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
First thing is to correct your function as pmdba wrote in his answer.
This would then be a correct function:
create or replace function getNum
return number
as
v_x number;
begin
SELECT COUNT(*) INTO v_x
FROM UserResponses WHERE NHSPlatform_Name = 'Improvement Data and Analytics';
return v_x;
end;
/
Then you need to call your function in correct way. This is one way of calling it:
select getNum from dual;
here is a small demo
Drop the ":" from the select statement:
create or replace function getNum
return number
as
v_x number;
begin
SELECT COUNT(*) INTO v_x
FROM UserResponses WHERE NHSPlatform_Name = 'Improvement Data and Analytics';
return v_x;
end;
/
select getNum() from dual;
Try this:
SQL> VARIABLE ret_val NUMBER;
SQL> execute :ret_val := getnum;
PL/SQL procedure successfully completed.
SQL> select :ret_val from dual;

Why a type cannot be constrained?

I am struggling with the following code:
DECLARE
TOTACID TAB_OF_ID(50);
RES NUMBER;
BEGIN
SELECT DISTINCT ID INTO TOTACID
FROM TABLE_B;
FOR indx IN 1 .. TOTACID.COUNT
LOOP
RES := F_IMPORT(TOTACID(indx));
DBMS_OUTPUT.PUT_LINE ('Moved ID ' || RES);
END LOOP;
END;
/
When I run it, it fails with the error:
Error report -
ORA-06550: line 2, column 11:
PLS-00566: type name "TAB_OF_ID" cannot be constrained
ORA-06550: line 5, column 19:
PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got NUMBER
ORA-06550: line 5, column 3:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Where TAB_OF_ID has been declared as follows:
create or replace TYPE TAB_OF_ID AS table of NUMBER(19,2);
I don't understand what is wrong. It seems that I cannot declare TOTACID TAB_OF_ID(50) but in a function I created some days ago I could declare LIS_ID TAB_OF_ID := TAB_OF_ID(50); and it works properly.
What is the difference with the script I have here?
Obviously TOTACID TAB_OF_ID(50) is different to LIS_ID TAB_OF_ID := TAB_OF_ID(50); The command is like
{variable name} {data type} := {inital value};
where := {inital value} is optional.
TOTACID TAB_OF_ID(50) would mean
{variable name} {inital value};
which is not valid syntax.
You can not declare the variable by assigning your table a fixed number of records, so you need something like:
DECLARE
TOTACID TAB_OF_ID;
RES NUMBER;
BEGIN
SELECT DISTINCT ID bulk collect INTO TOTACID
FROM TABLE_B;
...
END;
/
Also, notice that you are fetching more than one value, so you need BULK COLLECT INTO.
About
LIS_ID TAB_OF_ID := TAB_OF_ID(50);
here you are not declaring a variable with a given number of records, but you are assigning to a variable the 50th value of the table.

How do I CAST a NUMBER to VARCHAR2 in Oracle?

I have a problem with some P-SQL syntax. I have reduced the code sample to its minimum below.
The following works:
CREATE OR REPLACE FUNCTION MyFunction(LINE_ID SMALLINT)
RETURN VARCHAR2 IS
tmp VARCHAR2(4000);
BEGIN
tmp := CAST(LINE_ID AS VARCHAR2);
RETURN(tmp);
END MyFunction;
/
However, I need to change the LINE_ID parameter to NUMBER(5, 0), after which the following does not work:
CREATE OR REPLACE FUNCTION MyFunction2(LINE_ID NUMBER(5, 0))
RETURN VARCHAR2 IS
tmp VARCHAR2(4000);
BEGIN
tmp := CAST(LINE_ID AS VARCHAR2);
RETURN(tmp);
END MyFunction2;
/
The error message in Oracle SQL Developer 3.2.10.09 is
Error(1,36): PLS-00103: Encountered the symbol "(" when expecting one
of the following: := . ) , # % default character The symbol ":="
was substituted for "(" to continue.
How should I write the CAST statement in order to make it work with NUMBER(5, 0) instead of SMALLINT?
Again, this is not the original code but I am looking for a solution that does not deviate too much from the second version and preferably not another function call either. The VARCHAR2 return type is important as well.
The function you're looking for is TO_CHAR:
tmp := TO_CHAR(LINE_ID);
You can't specify NUMBER precision and scale for a function's parameter. Just declare it like this:
CREATE OR REPLACE FUNCTION MyFunction2(LINE_ID NUMBER)
The issue is not in your CAST, but rather in your parameter definition. From the documentation:
You can declare a formal parameter of a constrained subtype, like this:
DECLARE
SUBTYPE n1 IS NUMBER(1);
SUBTYPE v1 IS VARCHAR2(1);
PROCEDURE p (n n1, v v1) IS ...
But you cannot include a constraint in a formal parameter declaration, like this:
DECLARE
PROCEDURE p (n NUMBER(1), v VARCHAR2(1)) IS ...

What does this error mean and why does it appear?

I have a procedure that creates and declares different types. But every time I write 'create type' or 'declare type' I get this error:
ERROR line 4, col 10, ending_line 4, ending_col 18, Found 'recipient', Expecting: ( . # or % or .. := DEFAULT NOT NULL or ;
I use Oracle 10 and these are the first lines of the procedure. The error
CREATE OR REPLACE PROCEDURE ACTIVITE_PROD.NOTIF_NEW_HOLIDAY(v_USER_ID INTEGER, v_DURATION NUMBER, v_WEEK INTEGER, v_YEAR INTEGER) IS
-- this line causes the error
create type recipient as object (firstname varchar2, lastname varchar2, email varchar2);
-- this line also causes an error if modified and set first
declare
type recipients_list is table of recipient;
admins recipients_list := recipients_list();
What is wrong with my code?
From the Oracle Documentation Using PL/SQL With Object Types
Currently, you cannot define object types in a PL/SQL block, subprogram, or package. You can define them interactively in SQL*Plus using the SQL statement CREATE TYPE.