Error: Cannot invoke a PL/SQL function. Encountered the symbol "SELECT" - sql

I trying to make a function with a parameter in PL/SQL but getting following error: PLS-00103: Encountered the symbol "SELECT". Here is my code:
CREATE OR REPLACE FUNCTION select_by_id(id_in IN NUMBER) RETURN clients%ROWTYPE
AS
result clients%ROWTYPE;
BEGIN
SELECT * INTO result FROM clients WHERE client_id = id_in;
RETURN result;
END;
SELECT select_by_id(2) FROM DUAL;
What is the cause of the error, and how can the problem be fixed?

Your function works (for a certain degree of works) if you terminate it with / on a newline.
If you have the table:
CREATE TABLE clients (client_id, other) AS
SELECT 2, 'XYZ' FROM DUAL;
Then the function (terminated by a / on a newline):
CREATE OR REPLACE FUNCTION select_by_id(
id_in IN NUMBER
) RETURN clients%ROWTYPE
AS
result clients%ROWTYPE;
BEGIN
SELECT * INTO result FROM clients WHERE client_id = id_in;
RETURN result;
END;
/
Compiles and can be called from PL/SQL:
DECLARE
client CLIENTS%ROWTYPE := select_by_id(2);
BEGIN
DBMS_OUTPUT.PUT_LINE(client.client_id || ', ' || client.other);
END;
/
and outputs:
2, XYZ
However, a %ROWTYPE is a PL/SQL record type and cannot be used in an SQL statement so:
SELECT select_by_id(2) FROM DUAL;
Will not work because the data type is invalid in the SQL scope.
fiddle

Related

I need help regarding dynamic SQL and dynamically setting the table name in a function

So, i need to create a function that returns the count of the lines in a table, the table name must be specified by the user. This is the code i have:
CREATE OR REPLACE FUNCTION datiInTab( table regclass )
RETURNS NUMERIC(5) AS
$$
DECLARE
num NUMERIC(5);
cmd VARCHAR(1000):='SELECT COUNT(*) FROM ';
BEGIN
EXECUTE cmd || table;
RETURN num;
END;
$$
LANGUAGE plpgsql;
SELECT * FROM datiInTab(corsi);
And this is the error that returns after i execute:
ERROR: ERRORE: la colonna "corsi" non esiste
LINE 1: SELECT * FROM datiInTab(corsi); ^ SQL state: 42703 Character: 25
Meaning that the column "corsi" doesn't exist.
I debugged as much as i could and the only conclusion is that i don't really know what i need to do in order to make use of this dynamic call.
edit: regclass was a last minute addition, after trying with a simple varchar, that returned the same exact error
You can't name a variable table. it is a reserved word
and you have to pass a string else postgres thinks you want to pass a column
CREATE OR REPLACE FUNCTION datiInTab( table1 regclass )
RETURNS NUMERIC(5) AS
$$
DECLARE
num NUMERIC(5);
cmd VARCHAR(1000):='SELECT COUNT(*) FROM ';
BEGIN
EXECUTE cmd || table1;
RETURN num;
END;
$$
LANGUAGE plpgsql;
✓
SELECT * FROM datiInTab('corsi');
ERROR: relation "corsi" does not exist
LINE 1: SELECT * FROM datiInTab('corsi');
^
db<>fiddle here

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;

Pass SQL string to oracle stored procedure and get results with execute immediate

I am trying to pass in a SQL string to a stored procedure and using EXECUTE IMMEDIATE to return the results. Something like this:
CREATE PROCEDURE P360_RCT_COUNT (sqlString IN VARCHAR2)
AS
BEGIN
EXECUTE IMMEDIATE sqlString;
END;
/
I am not sure how to accomplish it. With the above, when I execute the SP using the command below, I get an error:
EXECUTE P360_RCT_COUNT 'SELECT COUNT(DISTINCT ENTITY_ID),ADDR_COUNTY FROM P360_V_RCT_COUNT GROUP BY ADDR_COUNTY';
The error is: ORA-06550: line 1, column 22:
PLS-00103: Encountered the symbol "SELECT COUNT(ENTITY_ID),ADDR_COUNTY
FROM P360_V_RCT_COUNT GROUP " when expecting one of the following:
:= . ( # % ; The symbol ":=" was substituted for "SELECT
COUNT(DISTINCT ENTITY_ID),ADDR_COUNTY FROM P360_V_RCT_COUNT GROUP " to
continue.
Basically I am building a SQL string in a system and need to pass it in to the SP and get the results back to the system. I am relatively new to stored procedures in Oracle.
The easiest way to work with a result set is sys_refcursor. This can be used quite easily with JDBC or ODBC.
Your procedure would look like this:
CREATE PROCEDURE P360_RCT_COUNT (
sqlString IN VARCHAR2
, p_result_set out sys_refcursor)
AS
BEGIN
open p_result_set for sqlString;
END;
/
Obviously the precise details of how you call it will vary according to your client. But in SQL*Plus it would be:
var rc refcursor
exec P360_RCT_COUNT( 'SELECT COUNT(DISTINCT ENTITY_ID),ADDR_COUNTY FROM P360_V_RCT_COUNT GROUP BY ADDR_COUNTY', :rc);
print rc
To return lists of values in a OUT parameter you need to decide the type(s) to use.
Say, for example, you have to return some varchar2 and some date lists, you could use something like this:
create or replace type tabOfVarchar2 is table of varchar2(100);
create or replace type tabOfDates is table of date;
create or replace procedure testProc(pString IN varchar2,
pOutVarchar1 OUT tabOfVarchar2,
pOutVarchar2 OUT tabOfVarchar2,
pOutVarchar3 OUT tabOfVarchar2,
pOutDates OUT tabOfDates
) is
begin
execute immediate pString
bulk collect into pOutVarchar1, pOutVarchar2, pOutVarchar3, pOutDates;
end;
This is way you can test this procedure:
declare
v1 tabOfVarchar2 ;
v2 tabOfVarchar2;
v3 tabOfVarchar2;
d1 tabOfDates ;
vSQL varchar2(100) := 'select ''a'', ''b'', ''c'', sysdate from dual';
begin
testProc(vSQL, v1, v2, v3, d1);
--
for i in v1.first .. v1.last loop
dbms_output.put_line(v1(i) || '/' || v2(i) || '/' || v3(i) || '/' || to_char(d1(i), 'dd/mm/yyyy'));
end loop;
end;
which gives:
a/b/c/14/04/2017
This only works with queries that give exactly a fixed number of columns, of known types.

postgresql function error: column name does not exist

i've implemented a function that check if a value appears in a specific row of a specific table:
CREATE FUNCTION check_if_if_exist(id INTEGER, table_name character(50), table_column character(20) ) RETURNS BOOLEAN AS $$
DECLARE res BOOLEAN;
BEGIN
SELECT table_column INTO res
FROM table_name
WHERE table_column = id;
RETURN res;
END;
$$ LANGUAGE plpgsql
i've create and fill a simple test table for try this function:
CREATE TABLE tab(f INTEGER);
and i call function like
SELECT check_if_exist(10, tab, f);
but i occurs in this error:
ERROR: column "prova" does not exist
LINE 1: SELECT check_if_exist(10, tab, f);
^
********** Error **********
ERROR: column "tab" does not exist
SQL state: 42703
Character: 27
why?
In addition to Elmo response you must be careful with types. You have got:
ERROR: column "tab" does not exist
because SQL parser do not know how to deal with tab which is without quote. Your query must be like:
SELECT check_if_exist(10, 'tab', 'f');
As Elmo answered you use dynamic query, so even if you quote tab you will got error:
ERROR: relation "table_name" does not exist
so you can use EXECUTE, example:
CREATE OR REPLACE FUNCTION check_if_exist(id INTEGER, table_name varchar, table_column varchar) RETURNS BOOLEAN AS $$
DECLARE
sql varchar;
cnt int;
BEGIN
sql := 'SELECT count(*) FROM ' || quote_ident(table_name) || ' WHERE ' || quote_ident(table_column) || '=$1';
RAISE NOTICE 'sql %', sql;
EXECUTE sql USING id INTO cnt;
RETURN cnt > 0;
END;
$$ LANGUAGE plpgsql
You can also use VARCHAR instead of character(N) in function arguments and use CREATE OR REPLACE FUNCTION ... instead of just CREATE FUNCTION ... which is very handy at debugging.
Your code has no chance to work - when dealing with different tables in PLPGSQL you need to utilize dynamic queries, so EXECUTE is required - http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
But first of all - there is nothing bad in using PostgreSQL EXISTS - http://www.postgresql.org/docs/current/static/functions-subquery.html#AEN15284 instead of inventing your own - performance of your solution will be significantly worse than using included batteries...
Hopefully this is helpful. Good luck.

Executing SQL Function using toad

I am very new to DB. I am java developer and nothing to do with SQL Functions.
But now I am in a situation where I need to check whether an sql function is getting executed properly on db or not
CREATE OR REPLACE FUNCTION RATELIMIT_OWN.Get_Logs ( p_yyyymm VARCHAR2, p_numec NUMBER )
RETURN LOG_RECORD_TABLE PIPELINED IS
TYPE ref0 IS REF CURSOR;
cur0 ref0;
out_rec LOG_RECORD := log_record(NULL,NULL,NULL);
BEGIN
OPEN cur0 FOR
'SELECT eventid, errormsg, create_date from logs partition (LOGS_P' || p_yyyymm || ') where numec=:1'
USING p_numec;
LOOP
FETCH cur0 INTO out_rec.eventid, out_rec.msg, out_rec.create_date;
EXIT WHEN cur0%NOTFOUND;
PIPE ROW(out_rec);
END LOOP;
CLOSE cur0;
RETURN;
END Get_Logs;
/
How to execute this sql function in toad. I want to see the results like normal Select query output
To check a table valued function please try:
select * FROM table(RATELIMIT_OWN.Get_Logs('a', 1));
FOE EXECUTING THE FUNCTION
SELECT RATELIMIT_OWN.Get_Logs(....,...) FROM DUAL ;
AND
ORA-00904: MEAN COLUMN NAME IS NOT VALID PLSS CHECK THE COLUMN NAME
Try:
select RATELIMIT_OWN.Get_Logs(...) from dual;