Oracle Stored Procedure Call from iSQL PLUS Invalid Identifier - oracle

I have created a procedure using the following code using iSQL Plus on Firefox. The procedure compiles successfully.
create or replace procedure get_staff (
product_no in varchar2,
o_cursor out sys_refcursor)
is
begin
open o_cursor for
'select sr.name, sr.bonus from sales_staff sr inner join product p on p.sales_staff_id = sr.staff_id where product_no = ' || product_no ;
end;
I am trying to call this procedure using the following code
var rc refcursor
exec get_staff('A56',:rc)
print rc
I get the following error.
ERROR at line 1:
ORA-00904: "A56": invalid identifier
ORA-06512: at "AA2850.GET_STAFF", line 6
ORA-06512: at line 1
ERROR:
ORA-24338: statement handle not executed
SP2-0625: Error printing variable "rc"

in the case you have, there's no need for dynamic sql:
open o_cursor for
select sr.name, sr.bonus
from sales_staff sr
inner join product p
on p.sales_staff_id = sr.staff_id
where p.product_no = product_no;
if you were using dynamic SQL then ideally you would in most cases want to bind:
open o_cursor for
'select sr.name, sr.bonus
from sales_staff sr
inner join product p
on p.sales_staff_id = sr.staff_id
where p.product_no = :b1' using product_no;
failing that (edge cases, sometimes you want to avoid bind variables for skewed data), varchar2s need enclosing in quotes:
open o_cursor for
'select sr.name, sr.bonus
from sales_staff sr
inner join product p
on p.sales_staff_id = sr.staff_id
where p.product_no = ''' ||product_no||'''';
but you should escape single quotes and validate that product_no has no semi colons etc (i.e. careful of SQL injection)

Related

Compilation Errors in Procedure of Oracle 10g

I receive the following error when I compile this function:
Compilation errors for PROCEDURE HAR.REPORT_INCOME_PROC PLS-00103:
Encountered the symbol "" when expecting one of the following
I have try to google for that, but I cant my fault...
CREATE OR REPLACE PROCEDURE REPORT_INCOME_PROC IS
BEGIN
DELETE FROM HAR.REPORT_INCOME;
INSERT INTO HAR.REPORT_INCOME RI
(RI.INCOME,
RI.AREA,
RI.INCOME_TYPE,
RI.DATA_DATE,
RI.CREATE_DATE,
RI.UPDATE_DATE)
SELECT SUM(YD.HJJE) DRSR,
MDYS.JYDQ SYB,
1,
TRUNC(YD.KDSJ) RQ,
(select sysdate from dual) XZSJ,
(select sysdate from dual) XGSJ
FROM HYDATA.LD_YD YD
LEFT JOIN HYDATA.LD_KHXX KHXX
ON YD.TYRBH = KHXX.KHBH
LEFT JOIN HYDATA.LD_GS GS
ON YD.QYDZBH = GS.GSBH
LEFT JOIN HAR.REPORT_JY_MDYS MDYS
ON YD.QYDZBH = MDYS.GSBH
WHERE YD.KDSJ >= TRUNC(ADD_MONTHS(SYSDATE, -12), 'yy')
AND (YD.YDZT != 5)
AND (YD.CYRQZ != '20000000000000000001' OR YD.CYRQZ IS NULL)
AND (KHXX.KHLB != 4 OR KHXX.KHLB IS NULL)
AND (GS.GSJC NOT LIKE '%F%' OR GS.GSJC IS NULL)
GROUP BY TRUNC(YD.KDSJ), MDYS.JYDQ
ORDER BY MDYS.JYDQ ASC, TRUNC(YD.KDSJ) DESC;
COMMIT;
END;
Here is the error
Error: PLS-00103: Encountered the symbol "" when expecting one of the
following:
begin function package pragma procedure subtype type use
<an identifier> <a double-quoted delimited-identifier> form
current cursor external language Line: 1
Hi I believe you need to use EXECUTE IMMEDIATE on a PLSQL BLOCK when doing DML statements.
try this:
CREATE OR REPLACE PROCEDURE REPORT_INCOME_PROC IS
BEGIN
EXECUTE IMMEDIATE 'DELETE FROM HAR.REPORT_INCOME';
EXECUTE IMMEDIATE 'INSERT INTO HAR.REPORT_INCOME RI <the rest of your codes>';
END;

SQL to Stored Procedure

I am working on a project and there is a need to write stored procedure instead of SQL query. I have never done this before and I tried now by converting the written sql to a procedure. However, I couldn't get this error free and working. Any suggestions from you folks is very helpful in fixing this..
SQL:
create or replace
PROCEDURE MS_TST_PROC AS
BEGIN
DECLARE
l_organization varchar2(40);
l_framework varchar2(10);
l_sub_category_code varchar2(20);
l_sub_category varchar2(20);
l_TST_function varchar2(20);
l_questionnaire_name varchar2(20);
l_responded_on varchar2(20);
l_overall_score number(10);
l_target_score number(10);
l_maturity number(10,2);
l_full_name varchar2(20);
cursor c_get_details
is
select
ts.organization_name,
q.framework,
q.sub_category_code,
q.sub_category,
tst.tst_function,
q.questionnaire_name,
resp.responded_on ,
resp.overall_score,
ts.target_score,
Round((resp.overall_score / ts.target_score)*100,2) as Maturity,
users.first_name || ' ' || users.last_name as full_name
into
l_organization,
l_framework,
l_sub_category_code,
l_sub_category,
l_tst_function,
l_questionnaire_name,
l_responded_on,
l_overall_score,
l_target_score,
l_maturity,
l_full_name
from MS_CMM_QUESTIONNAIRE q
INNER JOIN MS_CMM_TARGET_SCORE ts
on q.sub_category_code = ts.sub_category_code
INNER JOIN MS_CMM_CSF_FUNCTIONS tst
on tst.sub_category_code = q.sub_category_code
INNER JOIN MS_QSM_QUESTIONNAIRE qsm
on q.QUESTIONNAIRE_NAME = qsm.QUE_NAME
INNER JOIN MS_QSM_QUESTNR_RESP resp
on resp.QUESTIONNAIRE_ID = qsm.QUE_ID
and resp.applies_to_object = ts.organization_name
INNER JOIN SI_USERS_T users
on users.user_name = resp.respondent;
END MS_TST_PROC;
and compilation error says:
Error(60,1): PLS-00103: Encountered the symbol "END" when expecting one of the following: begin function pragma procedure subtype type <an identifier> <a double-quoted delimited-identifier> current cursor delete exists prior
There are a couple of issues:
You have a DECLARE statement without a subsequent BEGIN or END statement.
You have a CURSOR with an INTO clause; they cannot both be there. If the query returns a single row then just use SELECT ... INTO ... (see below), otherise, if you have multiple rows you need to process then you could use a cursor loop.
Also, it is much easier to read (and to find unmatched DECLARE/BEGIN/END statements) if you format your code and maintain proper levels of indentation.
Something like this:
CREATE PROCEDURE MS_TST_PROC
AS
l_organization MS_CMM_TARGET_SCORE.ORGANIZATION%TYPE;
l_framework MS_CMM_QUESTIONNAIRE.FRAMEWORK%TYPE;
l_sub_category_code MS_CMM_QUESTIONNAIRE.SUB_CATEGORY_CODE%TYPE;
l_sub_category MS_CMM_QUESTIONNAIRE.SUB_CATEGORY%TYPE;
l_TST_function MS_CMM_CSF_FUNCTIONS.TST_FUNCTION%TYPE;
l_questionnaire_name MS_CMM_QUESTIONNAIRE.QUESTIONNAIRE_NAME%TYPE;
l_responded_on MS_QSM_QUESTNR_RESP.RESPONDED_ON%TYPE;
l_overall_score MS_QSM_QUESTNR_RESP.OVERALL_SCORE%TYPE;
l_target_score MS_CMM_TARGET_SCORE.TARGET_SCORE%TYPE;
l_maturity number(10,2);
l_full_name varchar2(20);
BEGIN
SELECT ts.organization_name,
q.framework,
q.sub_category_code,
q.sub_category,
tst.tst_function,
q.questionnaire_name,
resp.responded_on,
resp.overall_score,
ts.target_score,
Round((resp.overall_score / ts.target_score)*100,2),
users.first_name || ' ' || users.last_name
INTO l_organization,
l_framework,
l_sub_category_code,
l_sub_category,
l_tst_function,
l_questionnaire_name,
l_responded_on,
l_overall_score,
l_target_score,
l_maturity,
l_full_name
FROM MS_CMM_QUESTIONNAIRE q
INNER JOIN MS_CMM_TARGET_SCORE ts
on q.sub_category_code = ts.sub_category_code
INNER JOIN MS_CMM_CSF_FUNCTIONS tst
on tst.sub_category_code = q.sub_category_code
INNER JOIN MS_QSM_QUESTIONNAIRE qsm
on q.QUESTIONNAIRE_NAME = qsm.QUE_NAME
INNER JOIN MS_QSM_QUESTNR_RESP resp
on resp.QUESTIONNAIRE_ID = qsm.QUE_ID
and resp.applies_to_object = ts.organization_name
INNER JOIN SI_USERS_T users
on users.user_name = resp.respondent;
-- Do something with the values.
END MS_TST_PROC;
/

ORA:00900 - Invalid SQL Statement

I am new to the vast world of oracle. What I am trying to do is, creating a stored procedure and retrieve its result.
My procedure goes as
Create or Replace Procedure usp_RotaPlateProductie_Select(
afdelingId in varchar2,
productTypeId in varchar2,
productieData out sys_refcursor)
IS
Begin
Open productieData for
Select Rotaplateproductie.Batchnummer, Cpiplusproductieorder.Productnummer,
Product.Omschrijving, Productieresultaatrtplrol.Bruto_In_Meters
From Rotaplateproductie inner join Productieresultaatrtplrol on
Rotaplateproductie.Batchnummer = Productieresultaatrtplrol.Batchnummer
inner join Cpiplusproductieorder on
Productieresultaatrtplrol.ProductieNummer = Cpiplusproductieorder.ProductNummer
inner join Product on
Cpiplusproductieorder.Productnummer = Product.Productnummer
Where Rotaplateproductie.Afdelingid = '3144' and Rotaplateproductie.producttype = 'PT005'
END;
And using the below code I am trying to execute it.
var rc REFCURSOR
EXEC usp_RotaPlateProductie_Select('3144','PT005', :rc);
While executing the above lines I am getting Ora:00900 error.
When I run the query part of the procedure, it is running fine but with procedure it gives me error.
As Shareef pointed out you're missing a semicolon on the statement inside your procedure, but it doesn't look like you're actually creating it properly. You need a / after the procedure to tell Oracle to execute the code and actually do the creation. I think it's seeing the var and exec statements as part of a single call, which is incorrect. But I'm also not sure how you're running this; if it's in SQL Developer you need to 'run script' (F5) rather than just 'run'.
Create or Replace Procedure usp_RotaPlateProductie_Select(
p_afdelingId in varchar2,
p_productTypeId in varchar2,
p_productieData out sys_refcursor)
IS
Begin
Open p_productieData for
Select Rotaplateproductie.Batchnummer, Cpiplusproductieorder.Productnummer,
Product.Omschrijving, Productieresultaatrtplrol.Bruto_In_Meters
From Rotaplateproductie
inner join Productieresultaatrtplrol on
Rotaplateproductie.Batchnummer = Productieresultaatrtplrol.Batchnummer
inner join Cpiplusproductieorder on
Productieresultaatrtplrol.ProductieNummer = Cpiplusproductieorder.ProductNummer
inner join Product on
Cpiplusproductieorder.Productnummer = Product.Productnummer
Where Rotaplateproductie.Afdelingid = p_afdelingId
and Rotaplateproductie.producttype = p_productTypeId;
END;
/
var rc REFCURSOR
EXEC usp_RotaPlateProductie_Select('3144','PT005', :rc);
print :rc
I've switched to use the IN parameters, and I've taken the liberty of changing the names so you can distinguish between parameters and column names; they were the same which can cause confusion.
You might also find it useful to alias your tables; no functional difference but maybe easier to read:
Create or Replace Procedure usp_RotaPlateProductie_Select(
p_afdelingId in varchar2,
p_productTypeId in varchar2,
p_productieData out sys_refcursor)
IS
Begin
Open p_productieData for
Select rp.Batchnummer, cppo.Productnummer,
p.Omschrijving, pra.Bruto_In_Meters
From Rotaplateproductie rp
inner join Productieresultaatrtplrol par
on rp.Batchnummer = pra.Batchnummer
inner join Cpiplusproductieorder cppo
on pra.ProductieNummer = cppo.ProductNummer
inner join Product p
on cppo.Productnummer = p.Productnummer
Where rp.Afdelingid = p_afdelingId
and rp.producttype = p_productTypeId;
END;
/
If you get a message that the procedure compiled with warnings, do 'show errors' to get the details.
did you run the code
Select Rotaplateproductie.Batchnummer, Cpiplusproductieorder.Productnummer,
Product.Omschrijving, Productieresultaatrtplrol.Bruto_In_Meters
From Rotaplateproductie inner join Productieresultaatrtplrol on
Rotaplateproductie.Batchnummer = Productieresultaatrtplrol.Batchnummer
inner join Cpiplusproductieorder on
Productieresultaatrtplrol.ProductieNummer = Cpiplusproductieorder.ProductNummer
inner join Product on
Cpiplusproductieorder.Productnummer = Product.Productnummer
Where Rotaplateproductie.Afdelingid = '3144' and Rotaplateproductie.producttype = 'PT005'
i it works please reply
i think you miss semicolon in the end
;
#Mavrik edited
After adding semicolon in the end of the query, the procedure is
created properly. thanks but it is still returning the same error code
when I tried to execute it using the below code
var rc REFCURSOR EXEC usp_RotaPlateProductie_Select('3144','PT005',
:rc);
UPDATE 1:
if you have ora 00900 it may be because of
Oracle/PLSQL: ORA-00900 Error

Oracle stored procedure

Can anyone help me by telling me what is wrong with the following syntax? I am just trying to run a simple SELECT statement in a stored procedure.
CREATE OR REPLACE PROCEDURE PVSSRDB.GETBATTERYSTATUSFORALLLOGGERS
(
p_Logger OUT e.comment_,
p_tStamp OUT h.ts,
p_Val OUT h.value_number
)
AS
BEGIN
select
e.comment_,
max(h.ts),
avg(h.value_number)
INTO
p_Logger,
p_tStamp,
p_Val
FROM
PVSSRDB.ELEMENTS e inner join PVSSRDB.DB15MINHISTORY_00100009 h on h.element_id =e.element_id
WHERE
e.element_name like 'System1:H%.BatteryCondition'
GROUP BY
e.comment_
ORDER by 2 asc
END GETBATTERYSTATUSFORALLLOGGERS;
I keep getting the same 3 errors stating:
Error(9,3): PL/SQL: SQL Statement Ignored
Error(23,18): PL/SQL: ORA_00933: SQL command not properly ended
Error(24,34): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
You're missing a semicolon after the ORDER BY 2 asc
Also you need to declare your OUT parameters properly.
CREATE OR REPLACE
PROCEDURE PVSSRDB.GETBATTERYSTATUSFORALLLOGGERS (
p_Logger OUT PVSSRDB.ELEMENTS.comment_%TYPE,
p_tStamp OUT PVSSRDB.DB15MINHISTORY_00100009.ts%TYPE,
p_Val OUT PVSSRDB.DB15MINHISTORY_00100009.value_number%TYPE
)
AS
BEGIN
select e.comment_,
max(h.ts),
avg(h.value_number)
INTO p_Logger,
p_tStamp,
p_Val
FROM PVSSRDB.ELEMENTS e
inner join PVSSRDB.DB15MINHISTORY_00100009 h on (h.element_id =e.element_id)
WHERE e.element_name like 'System1:H%.BatteryCondition'
GROUP BY e.comment_
ORDER by 2 asc;
END GETBATTERYSTATUSFORALLLOGGERS;

Output results of Oracle stored proc from SQL Developer

I'm trying to call an Oracle stored proc using SQL Developer. The proc outputs results using a sys_refcursor. I right click in the proc window which brings up the Run PL/SQL window. When I choose the proc I want it creates all the input params etc for me. Below is the code I'm using to try and loop through the sys_refcursor and output the results, but I'm getting an error on the 'v_rec v_Return%rowtype;' line :
ORA-06550: line 6 column 9:
PLS-00320: the declaration of the type of this expression is incomplete or malformed.
ORA-06550: line 6 column 9:
PL/SQL: Item ignored
vendor code 6550
I found the looping code on a couple of other websites and it seems to be the way to do it but it's not working for me no matter what I try. Another question - on the DBMS_OUTPUT.PUT_LINE('name = ' || v_rec.ADM) am I referencing the v_rec correctly i.e. is v_rec."column_name" the correct way??
I'm not that used to Oracle and have never used SQL plus. Any suggestions appreciated.
DECLARE
P_CAE_SEC_ID_N NUMBER;
P_PAGE_INDEX NUMBER;
P_PAGE_SIZE NUMBER;
v_Return sys_refcursor;
v_rec v_Return%rowtype;
BEGIN
P_CAE_SEC_ID_N := NULL;
P_PAGE_INDEX := 0;
P_PAGE_SIZE := 25;
CAE_FOF_SECURITY_PKG.GET_LIST_FOF_SECURITY(
P_CAE_SEC_ID_N => P_CAE_SEC_ID_N,
P_PAGE_INDEX => P_PAGE_INDEX,
P_PAGE_SIZE => P_PAGE_SIZE,
P_FOF_SEC_REFCUR => v_Return
);
-- Modify the code to output the variable
-- DBMS_OUTPUT.PUT_LINE('P_FOF_SEC_REFCUR = ');
loop
fetch v_Return into v_rec;
exit when v_Return%notfound;
DBMS_OUTPUT.PUT_LINE('name = ' || v_rec.ADM);
end loop;
END;
Your problem is here:
v_Return sys_refcursor;
v_rec v_Return%rowtype;
v_Return is a cursor variable and has no specific structure (list of columns), so v_Return%rowtype is not a valid record structure to declare v_rec. It is even possible for different calls to the procedure to return cursors with different structures.
You know what you are expecting the structure of the returned cursor to be (but Oracle doesn't) so you need to explicitly define the appropriate record structure e.g.
type t_row is record (empno number, ename varchar2(30));
v_rec t_row;
You need a strongly typed ref cursor to be able to define it as a %ROWTYPE.
Example here
#Tony Andrews thanks for this it gave me a better idea where I was going wrong. Still having problems though - here's a shortened version of my proc. It's a bit complex in that it's selecting all fields from a subquery and 2 other values:
open p_fof_sec_refcur for
SELECT *
FROM(
SELECT securities.*, rownum rnum, v_total_count
FROM
(
SELECT
CFS.CAE_SEC_ID,
CFS.FM_SEC_CODE,
...
FROM
CAEDBO.CAE_FOF_SECURITY CFS
INNER JOIN caedbo.CAE_DATA_SET_ELEMENT CDSE_STAT
ON (CDSE_STAT.DATA_SET_ELEMENT_ID = CFS.APPR_STATUS)
...
WHERE APPR_STATUS = NVL(p_appr_status, APPR_STATUS)
...
)securities
)
WHERE rnum between v_pgStart and v_pgEnd;
I explicitly defined the output structure as below to match the return fields from the proc but I'm still getting an error:
v_Return sys_refcursor;
type t_row is record (CAE_SEC_ID NUMBER,FM_SEC_CODE VARCHAR2(7),...rnum number, v_total_count number);
v_rec t_row;
The error I get is
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
ORA-06512: at line 45
I'm just wondering is the "rownum rnum, v_total_count" part tripping me up. I'm pretty sure I have all the other fields in the output structure correct as I copied them directly from the proc.

Resources