Oracle Run Procedure with one in parameter and multiple out parameter - oracle

I just started working with Oracle and I'm using SQL Developer to test before I start adding stuff to my application, but I'm running into issues because Oracle behaves differently than every other database engine I've worked with.
I created a dummy table:
CREATE TABLE "ROOT"."EMPLOYEES"
( "ID" NUMBER NOT NULL ENABLE,
"FIRSTNAME" VARCHAR2(30 BYTE) NOT NULL ENABLE,
"LASTNAME" VARCHAR2(30 BYTE) NOT NULL ENABLE,
"EMAIL" VARCHAR2(40 BYTE) NOT NULL ENABLE,
CONSTRAINT "EMPLOYEES_PK" PRIMARY KEY ("ID")
)
And Then I created a Procedure:
create or replace PROCEDURE get_employee
(
emp_id IN NUMBER,
m_FirstName OUT Varchar2,
m_LastName OUT Varchar2,
m_Email OUT Varchar2
)
AS
BEGIN
SELECT
FirstName
,LastName
,Email
INTO
m_FirstName,
m_LastName,
m_Email
FROM EMPLOYEES
WHERE
ID = emp_id;
END get_employee;
The problem is I get compilation errors when I try to run the procedure:
Declare x VARCHAR2(30);
y VARCHAR2(30);
z VARCHAR2(40);
Begin
exec GET_EMPLOYEE(1, :x, :y, :z);
SYS.DBMS_OUTPUT.PUT_LINE(x);
End;
I get this error:
ORA-06550: line 8, column 4:
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
an identifier a double-quoted
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
PL/SQL procedure successfully completed.
I'm really not sure how to change my call to the procedure to make it work with SQL Developer. Any help would be greatly appreciated.

This is the correct syntax
Declare
x VARCHAR2(30);
y VARCHAR2(30);
z VARCHAR2(40);
Begin
GET_EMPLOYEE(1, x, y, z);
DBMS_OUTPUT.PUT_LINE(x);
End;

Or an another version of stub execution.
var x varchar2(30);
var y varchar2(30);
var z varchar2(40);
exec GET_EMPLOYEE(1, :x, :y, :z);

Related

Invalid reference in Oracle database

I am using Oracle database 19c for a project. I have created the alumni table as shown below:
CREATE TABLE Alumni (
ID NUMBER GENERATED ALWAYS AS IDENTITY ,
First_Name varchar2(20) NOT NULL,
Last_Name varchar2(20) NOT NULL,
Gender char(1) NOT NULL,
CHECK (Gender IN('M','F')),
Graduation_Year number NOT NULL,
check (Graduation_Year>=1980 AND Graduation_Year<=2020),
Degree_Course varchar2(255) not null,
Award_Nominated CHAR(1),
CHECK (Award_Nominated IN('Y','N')),
Award_Won CHAR(1),
CHECK (Award_Won IN('Y','N')),
Phone_Number VARCHAR2(15) not null,
Email_Address VARCHAR2(255) not null,
CONSTRAINT ALUM_PK PRIMARY KEY(ID)
);
Then I tried to define a function that will allow me to search by First or last name in a section of the table, shown below:
CREATE OR REPLACE TYPE alum_row_type is object(ID number,First_name varchar2(20),Last_Name
varchar2(20),Phone_number varchar2(15),Email_Address varchar2(255));
CREATE OR REPLACE TYPE t_alum_row_type as table of alum_row_type;
CREATE OR REPLACE FUNCTION Name_Search RETURN t_alum_row_type
IS
L_alum_row t_alum_row_type := t_alum_row_type();
X integer :=0;
BEGIN
FOR R IN (SELECT ID,First_Name, Last_Name,Phone_Number,Email_Address FROM alumni)
LOOP
L_alum_row.extend;
X:=X+1;
L_alum_row(X):= alum_row_type(X.ID,X.First_Name, X.Last_Name, X.Phone_Number, X.Email_Address);
END LOOP;
RETURN L_alum_row;
END;
After running this, I get this error:
LINE/COL ERROR
--------- -------------------------------------------------------------
10/9 PL/SQL: Statement ignored
10/41 PLS-00487: Invalid reference to variable 'X'
Errors: check compiler log
How can I resolve this issue. I am relatively new to PL\SQL, so please explain it simply.
This is not possible
L_alum_row(X):= alum_row_type(X.ID,X.First_Name, X.Last_Name, X.Phone_Number, X.Email_Address);
You are referencing X.ID, X.Phone_Number etc. . . but declared X as an integer. If you are trying to access the current loop record, try with
L_alum_row(X):= alum_row_type(R.ID,R.First_Name, R.Last_Name, R.Phone_Number, R.Email_Address);
As you declared the loop iterator as R for your cursor
FOR R IN (SELECT ID,First_Name, Last_Name,Phone_Number,Email_Address FROM alumni)
You can eliminate the loop altogether by using BULK COLLECT. Thereby reducing the function to basically a single select statement.
function name_search
return t_alum_row_type
is
l_alum_row t_alum_row_type := t_alum_row_type();
begin
select alum_row_type(id,first_name, last_name,phone_number,email_address)
bulk collect
into l_alum_row
from alumni;
return l_alum_row;
end;

How can I deal with PL-SQL package error PLS-00103: Encountered the symbol "(" when expecting one of the following: := )

There is a similar answer for the problem I have, but it seems that this answer is for procedure issue.
I supposed to make a pl sql package which has 3 procedures inside. It's gonna be like that:
CREATE OR REPLACE PACKAGE Count_num AS
PROCEDURE count_emps(dno IN number);
PROCEDURE count_deps(empssn IN char(9));
PROCEDURE delete_deps(empssn IN char(9), dname IN varchar2(15));
END;
/
show errors
CREATE OR REPLACE PACKAGE BODY Count_num AS
PROCEDURE count_emps(dno IN number)
AS
cnt number;
BEGIN
SELECT COUNT(*) INTO cnt
WHERE Department.dnumber = Employee.dno
AND Department.dnumber = dno;
dbms_output.put_line('Number of Employee is ' || cnt);
END;
PROCEDURE count_deps(empssn IN char(9))
AS
cnt2 number;
BEGIN
SELECT COUNT(*) INTO cnt2
WHERE Dependent.essn = Employee.ssn
AND Department.essn = empssn;
dbms_output.put_line('Number of dependent is ' || cnt2);
END;
PROCEDURE delete_deps(empssn IN char(9), dname IN varchar2(15))
AS
BEGIN
DELETE *
FROM Dependent
WHERE Dependent.essn = Employee.ssn
AND Dependent.essn = empssn
AND Dependent.dependent_name = dname;
SELECT *
FROM Dependent
WHERE Dependent.essn = Employee.ssn
AND Dependent.essn = empssn
AND Dependent.dependent_name = dname;
END;
END;
/
show errors
EXEC Count_num.count_emps(5);
EXEC Count_num.count_deps('333445555');
EXEC Count_num.delete_deps('333445555', 'Alice')
show errors
count_emps counts the number of employees for a department,
count_deps counts the number of dependents for a valid employee,
delete_deps deletes a specific depdendent. It's creation query is like below:
drop table Employee cascade constraints;
commit;
create table Employee
(
fname varchar2(15),
minit varchar2(1), -- can be char
lname varchar2(15),
ssn char(9),
bdate date,
address varchar2(50),
sex varchar2(1) CHECK(Sex = 'M' or Sex = 'F'),
salary number, -- need to put check on salary
superssn char(9),
dno number DEFAULT 0,
constraint EMPPK
primary key(ssn),
constraint EMPSUPERVRFK
foreign key(superssn) references Employee(ssn)
ON DELETE SET NULL
);
drop table Department cascade constraints;
commit;
create table Department
(
dname varchar2(15) NOT NULL,
dnumber number,
mgr_ssn char(9) DEFAULT '000000000',
mgr_start_date date,
constraint DEPTPK
primary key(dnumber),
constraint DEPTMGRFK
foreign key(mgr_ssn) references Employee(ssn)
ON DELETE SET NULL
);
drop table Dependent cascade constraints;
commit;
create table Dependent
(
Essn char(9),
Dependent_name varchar2(15),
Sex varchar2(15),
Bdate date,
Relationship varchar2(15),
constraint DEPENDPK
primary key (Essn, Dependent_name),
constraint DEPENDFK
foreign key(Essn) references Employee(Ssn)
);
When I execute package queries, it gives me an error like below:
SQL> CREATE OR REPLACE PACKAGE Count_num AS
2 PROCEDURE count_emps(dno IN number);
3 PROCEDURE count_deps(empssn IN char(9));
4 PROCEDURE delete_deps(empssn IN char(9), dname IN varchar2(15));
5 END;
6 /
Warning: Package created with compilation errors.
Elapsed: 00:00:00.02
SQL> show errors
Errors for PACKAGE COUNT_NUM:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/37 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
:= ) , default varying character large
The symbol ":=" was substituted for "(" to continue.
4/38 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
:= ) , default varying character large
The symbol ":=" was substituted for "(" to continue.
4/60 PLS-00103: Encountered the symbol "(" when expecting one of the
LINE/COL ERROR
-------- -----------------------------------------------------------------
following:
:= . ) , # % default character
The symbol ":=" was substituted for "(" to continue.
I can't recognize what this error is, so anyone can explain what this error is, and how can I handle this issue?
Remove the length specified for the data types in the arguments.
Also, better to specify the column data type than hard-coding it.
CREATE OR REPLACE PACKAGE Count_num AS
PROCEDURE count_emps(i_dno IN employee.dno%TYPE);
PROCEDURE count_deps(i_empssn IN employee.ssn%TYPE);
PROCEDURE delete_deps(i_empssn IN employee.ssn%TYPE,
i_dname IN department.dname%TYPE
);
END;
/

Oracle error: expression '' cannot be used as an assignment target

When I try to execute the stored procedure, all the parameters that I pass to it, appears "expression '(parameter)' cannot be used as an assignment target", I don't know what the problem is.
This is the stored procedure:
create or replace PROCEDURE INSTERT_UPDATE_EMPLEADO
(
CEDULA IN OUT INTEGER,
ID_CARGO IN OUT INTEGER,
ID_EMP IN OUT INTEGER,
NOMBRE IN OUT VARCHAR,
APELLIDO IN OUT VARCHAR,
FECHA_NAC IN OUT INTEGER,
FECHA_CON IN OUT INTEGER,
SALARIO IN OUT INTEGER
) AS
BEGIN
IF ID_EMP = 0 THEN
INSERT INTO EMPLEADO("CEDULA_EMPLEADO", "ID_CARGO", "EMPLEADO_ID", "NOMBRE", "APELLIDO", "FECHA_NAC", "FECHA_CONTRATO", "SALARIO")
VALUES (CEDULA, ID_CARGO, ID_EMP, NOMBRE, APELLIDO, FECHA_NAC, FECHA_CON, SALARIO);
ELSE
UPDATE EMPLEADO SET NOMBRE = NOMBRE, APELLIDO = APELLIDO, FECHA_NAC = FECHA_NAC, FECHA_CONTRATO = FECHA_CON, SALARIO = SALARIO,
CEDULA_EMPLEADO = CEDULA, ID_CARGO = ID_CARGO WHERE EMPLEADO_ID = ID_EMP;
END IF;
COMMIT;
END INSTERT_UPDATE_EMPLEADO;
Since you are going to insert or update the table, you need to create the table first.
If you already have the table, please ignore this step:
create table EMPLEADO
(
CEDULA NUMBER(5),
ID_CARGO NUMBER(5),
ID_EMP NUMBER(5),
NOMBRE VARCHAR2(20),
APELLIDO VARCHAR2(20),
FECHA_NAC NUMBER(5),
FECHA_CON NUMBER(5),
SALARIO NUMBER(5)
)
Then create the stored procedure:
CREATE OR REPLACE PROCEDURE INSTERT_UPDATE_EMPLEADO(
P_CEDULA IN EMPLEADO.CEDULA%TYPE,
P_ID_CARGO IN EMPLEADO.ID_CARGO%TYPE,
P_ID_EMP IN EMPLEADO.ID_EMP%TYPE,
P_NOMBRE IN EMPLEADO.NOMBRE%TYPE,
P_APELLIDO IN EMPLEADO.APELLIDO%TYPE,
P_FECHA_NAC IN EMPLEADO.APELLIDO%TYPE,
P_FECHA_CON IN EMPLEADO.FECHA_CON%TYPE,
P_SALARIO IN EMPLEADO.SALARIO%TYPE)
IS
BEGIN
IF P_ID_EMP = 0 THEN
INSERT INTO EMPLEADO("CEDULA_EMPLEADO", "ID_CARGO", "EMPLEADO_ID", "NOMBRE", "APELLIDO", "FECHA_NAC", "FECHA_CONTRATO", "SALARIO")
VALUES (P_CEDULA, P_ID_CARGO, P_ID_EMP, P_NOMBRE, P_APELLIDO, P_FECHA_NAC, P_FECHA_CON, P_SALARIO);
ELSE
UPDATE EMPLEADO
SET NOMBRE = P_NOMBRE,
APELLIDO = P_APELLIDO,
FECHA_NAC = P_FECHA_NAC,
FECHA_CONTRATO = P_FECHA_CON,
SALARIO = P_SALARIO,
CEDULA_EMPLEADO = P_CEDULA,
ID_CARGO = P_ID_CARGO
WHERE EMPLEADO_ID = P_ID_EMP;
END IF;
COMMIT;
END;
The problem not in the procedure itself, but in its interface. out and in out parameters write their values back as output. For example:
create table demo (id integer);
Procedure (creates without errors):
create or replace procedure insert_demo
( id in out demo.id%type )
as
begin
insert into demo (id) values (id);
end insert_demo;
Call fails, because the literal value 1 can't be updated with the out value returned by the procedure:
SQL> exec insert_demo(1)
BEGIN insert_demo(1); END;
*
ERROR at line 1:
ORA-06550: line 1, column 19:
PLS-00363: expression '1' cannot be used as an assignment target
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
If you are going to use out or in out parameters, you have to pass variables (SQL*Plus example below, though you could just call it from another procedure passing a normal PL/SQL variable):
SQL> var id number
SQL> exec :id := 1
PL/SQL procedure successfully completed.
ID
----------
1
SQL> exec insert_demo(:id)
PL/SQL procedure successfully completed.
ID
----------
1
The solution is therefore either to pass variables, or to change the parameter mode to in:
create or replace procedure insert_demo
( id in demo.id%type )
as
begin
insert into demo (id) values (id);
end insert_demo;
Test:
SQL> exec insert_demo(1)
PL/SQL procedure successfully completed.
It is generally good practice to avoid using column names for PL/SQL parameters and variables, for example by prefixing parameters with p_ and local variables with l_. Or if you must, you can use dot notation and the procedure name, e.g. insert_demo.id or instert_update_empleado.salario would specify the procedure parameter and not the table column. However, that is not the cause of the issue here.
(Also, your caps lock is on.)

Capture error using OUT parameter in Oracle's procedure

I have to create procedure to insert row into table, also I need to include am OUT parameter that would capture any errors. However when I test using anonymous block it would not work, but if I use exception in procedure it is working. It means if I add an OUT parameter and I pass values from the block it won't work.
This code works but is not what I want:
create or replace
PROCEDURE EXAM_SP
(P_FIRSTNAME IN BB_SHOPPER.FIRSTNAME%TYPE,
P_LASTNAME IN BB_SHOPPER.LASTNAME%TYPE,
P_ADDRESS IN BB_SHOPPER.ADDRESS%TYPE,
P_CITY IN BB_SHOPPER.CITY%TYPE,
P_STATE IN BB_SHOPPER.STATE%TYPE,
P_ZIP IN BB_SHOPPER.ZIPCODE%TYPE)
IS
BEGIN
INSERT INTO BB_SHOPPER (IDSHOPPER, FIRSTNAME, LASTNAME, ADDRESS, CITY,
STATE, ZIPCODE)
VALUES
(BB_SHOPPER_IDSHOPPER_SEQ.NEXTVAL,P_FIRSTNAME,P_LASTNAME,P_ADDRESS,
P_CITY, P_STATE,P_ZIP);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error Code = '||SQLCODE);
DBMS_OUTPUT.PUT_LINE('Error Message = Please check input');
END EXAM_SP;.
But in code above if I name out parameter it won't work, not sure how to do this, if I add OUT parameter to procedure and pass values:
create or replace
PROCEDURE EXAM_SP
(P_FIRSTNAME IN VARCHAR2,
P_LASTNAME IN VARCHAR2,
P_ADDRESS IN VARCHAR2,
P_CITY IN VARCHAR2,
P_STATE IN CHAR,
P_ZIP IN VARCHAR2,
P_ERROR OUT VARCHAR2)......
I will receive this error
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
If I remove parameter and use original code on the beginning it works.
Anonymous block that gets that error:
DECLARE
LV_FIRSTNAME_TXT BB_SHOPPER.FIRSTNAME%TYPE := 'FIRST';
LV_LASTNAME_TXT BB_SHOPPER.LASTNAME%TYPE := 'LAST';
LV_ADDRESS_TXT BB_SHOPPER.ADDRESS%TYPE := '8899 TAPE PARK';
LV_CITY_TXT BB_SHOPPER.CITY%TYPE := 'JACKSONVILLE';
LV_STATE_TXT BB_SHOPPER.STATE%TYPE := 'FLd';
LV_ZIP_NUMBER BB_SHOPPER.ZIPCODE%TYPE := '34567';
LV_ERROR varchar2(100);
BEGIN
EXAM_SP(LV_FIRSTNAME_TXT, LV_LASTNAME_TXT, LV_ADDRESS_TXT,
LV_CITY_TXT,LV_STATE_TXT,LV_ZIP_NUMBER);
DBMS_OUTPUT.PUT_LINE(LV_ERROR);
END;
Procedure:
create or replace
PROCEDURE EXAM_SP
(P_FIRSTNAME IN VARCHAR2,
P_LASTNAME IN VARCHAR2,
P_ADDRESS IN VARCHAR2,
P_CITY IN VARCHAR2,
P_STATE IN CHAR,
P_ZIP IN VARCHAR2,
P_ERROR OUT VARCHAR2)
IS
BEGIN
INSERT INTO BB_SHOPPER (IDSHOPPER, FIRSTNAME, LASTNAME, ADDRESS, CITY,
STATE, ZIPCODE)
VALUES
(BB_SHOPPER_IDSHOPPER_SEQ.NEXTVAL,P_FIRSTNAME,P_LASTNAME,P_ADDRESS,
P_CITY, P_STATE,P_ZIP);
EXCEPTION
WHEN OTHERS THEN
P_ERROR := SQLCODE;
/*DBMS_OUTPUT.PUT_LINE('Error Code = '||SQLCODE);
DBMS_OUTPUT.PUT_LINE('Error Message = Please check input');
P_ERROR := SQLCODE;*/
END EXAM_SP;
Error message that I am receiving:
Error report:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 6
06502. 00000 - "PL/SQL: numeric or value error%s"
I have passed variable 'FLd' to procedure parameter in order to test error capture.
Table structure:
IDSHOPPER NUMBER(4,0)
FIRSTNAME VARCHAR2(15 BYTE)
LASTNAME VARCHAR2(20 BYTE)
ADDRESS VARCHAR2(40 BYTE)
CITY VARCHAR2(20 BYTE)
STATE CHAR(2 BYTE)
ZIPCODE VARCHAR2(15 BYTE)
PHONE VARCHAR2(10 BYTE)
FAX VARCHAR2(10 BYTE)
EMAIL VARCHAR2(25 BYTE)
USERNAME VARCHAR2(8 BYTE)
PASSWORD VARCHAR2(8 BYTE)
COOKIE NUMBER(4,0)
DTENTERED DATE
PROVINCE VARCHAR2(15 BYTE)
COUNTRY VARCHAR2(15 BYTE)
...
"If I add out parameter to procedure and I pass values I will receive this error"
Alex has provided the long answer, I'm just going to make one short point: this is bad practice. Most programming languages include built-in functionality for handling exceptions. What you propose creates two architectural problems:
Programs which call your procedure have to write non-standard code to catch errors, which is just a pain for both the developers who write the calling programs and everybody else who has to understand how they work.
Your procedure doesn't hurl an exception so even though it "failed" it returns a success state to calling programs. If the developer who wrote the calling program didn't implement the special code the exception is lost and the database can be left in an invalid state.
The error stack shows:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 6
06502. 00000 - "PL/SQL: numeric or value error%s"
That stack shows, partly because it doesn't mention the procedure name, that the error is from line 6 of the anonymous block. It isn't getting as far as the call to the procedure on line 11 of that block.
The problem is that you've defined the local state variable:
LV_STATE_TXT BB_SHOPPER.STATE%TYPE := 'FLd';
using the %TYPE syntax, which is great; but as the table column is char(2), when you try to assign the three-character text literal 'Fld' to that two-character local variable it immediately errors at that point.
it is not getting as far as sending the three-character value to the procedure, so the error you're expecting from the insert doesn't appear because the insert doesn't happen either.
If you want to break it with that particular error you can either change the local variable declaration to be a fixed length instead of using %TYPE as you would normally want to:
DECLARE
LV_FIRSTNAME_TXT BB_SHOPPER.FIRSTNAME%TYPE := 'FIRST';
LV_LASTNAME_TXT BB_SHOPPER.LASTNAME%TYPE := 'LAST';
LV_ADDRESS_TXT BB_SHOPPER.ADDRESS%TYPE := '8899 TAPE PARK';
LV_CITY_TXT BB_SHOPPER.CITY%TYPE := 'JACKSONVILLE';
--LV_STATE_TXT BB_SHOPPER.STATE%TYPE := 'FLd';
-- specific length to allow invalid value to be used
LV_STATE_TXT char(3) := 'FLd';
LV_ZIP_NUMBER BB_SHOPPER.ZIPCODE%TYPE := '34567';
LV_ERROR varchar2(100);
BEGIN
EXAM_SP(LV_FIRSTNAME_TXT, LV_LASTNAME_TXT, LV_ADDRESS_TXT,
LV_CITY_TXT,LV_STATE_TXT,LV_ZIP_NUMBER,LV_ERROR);
DBMS_OUTPUT.PUT_LINE(LV_ERROR);
END;
/
-12899
PL/SQL procedure successfully completed.
Or more simply use literals directly for the IN parameters, as you are just testing the procedure at this point:
DECLARE
LV_ERROR varchar2(100);
BEGIN
EXAM_SP('FIRST', 'LAST', '8899 TAPE PARK',
'JACKSONVILLE', 'FLd', '34567', LV_ERROR);
DBMS_OUTPUT.PUT_LINE(LV_ERROR);
END;
/
-12899
PL/SQL procedure successfully completed.
You might find it more useful to return the error text, not just the number (and if you're returning the error number use a numeric formal argument type!), e.g:
...
EXCEPTION
WHEN OTHERS THEN
P_ERROR := SQLERRM;
END EXAM_SP;
/
-- same anonymous block
ORA-12899: value too large for column "MY_SCHEMA"."BB_SHOPPER"."STATE" (actual: 3, maximum: 2)
PL/SQL procedure successfully completed.
Of course, as I mentioned in a comment, it's better to let Oracle's exception handling just bubble the actual exception up to the caller - aside maybe from logging, you should only really catch exceptions you can actually handle. Notice that the error message that's passed back doesn't tell you anything about where the error occurred in the code; without the exception handler you would see the line number in the procedure that had the offending statement. And as APC points out, every caller has to look for and handle the resposne, and it would be easy to overlook. There are always exceptions (ha) of course, but this seems to be an exercise in doing things wrong.

Oracle Passing Custom Table Type To Stored Procedure

FYI: Oracle 12c
I have created a custom type called Payeezy_Error:
create or replace TYPE PAYEEZY_ERROR
AS
OBJECT (
CODE VARCHAR(30),
DESCRIPTION VARCHAR(200)
);
And then in turn created a Table type of Payeezy_Errors:
create or replace TYPE PAYEEZY_ERRORS AS TABLE OF PAYEEZY_ERROR;
I then have a Procedure that takes Payeezy_Errors as an IN parameter:
create or replace PROCEDURE SAVE_USER_PAYMENT_TRANSACTION
(
in_AccountID IN VARCHAR2,
in_SequenceID IN VARCHAR2,
in_CorrelationID IN VARCHAR2,
in_TransactionID IN VARCHAR2,
in_TransactionTag IN VARCHAR2,
in_Currency IN VARCHAR2,
in_TransactionType IN VARCHAR2,
in_BankResponse IN VARCHAR2,
in_GatewayResponse IN VARCHAR2,
in_ValidationStatus IN VARCHAR2,
in_TransactionStatus IN VARCHAR2,
in_Errors IN PAYEEZY_ERRORS
)
AS
var_uptID NUMBER;
var_ErrorCount NUMBER := 0;
EX_AUTHENTICATION EXCEPTION;
BEGIN
-- Insert the Payeezy Response values tied to the user
INSERT INTO
USER_PAYMENT_TRANSACTION (
ACCOUNT_ID, UP_PAYMENT_SEQ_ID, CORRELATION_ID, TRANSACTION_ID,
TRANSACTION_TAG, CURRENCY, TRANSACTION_TYPE, BANK_RESPONSE,
GATEWAY_RESPONSE, VALIDATION_STATUS, TRANSACTION_STATUS
) VALUES (
in_AccountID, in_SequenceID, in_CorrelationID, in_TransactionID,
in_TransactionTag, in_Currency, in_TransactionType, in_BankResponse,
in_GatewayResponse, in_ValidationStatus, in_TransactionStatus
)
RETURNING
ID
INTO
var_uptID;
-- Insert any errors that may be associated with a failure/unsuccessful transaction
SELECT
COUNT(*)
INTO
var_ErrorCount
FROM
in_Errors;
IF (var_ErrorCount > 0) THEN
INSERT INTO
USER_PAYMENT_TRANSACTION_ERROR (
UPT_ID, CODE, DESCRIPTION
)
SELECT
var_uptID, e.CODE, e.DESCRIPTION
FROM
in_Errors;
END IF;
-- Exception Handling
EXCEPTION
WHEN EX_AUTHENTICATION THEN
raise_application_error(-20001, 'Authentication Failed.');
END SAVE_USER_PAYMENT_TRANSACTION;
When I compile the procedure it yells at me at the SELECT COUNT(*) statement that:
ORA-00942: table or view does not exist.
And red-dashes are under SELECT and in_Errors.
Further down the procedure I get the same error and the second INSERT INTO and in_Errors lines are red-dashes too.
I have exited and reloaded Oracle SQL Developer just to see if it was a caching thing. I have searched around the web but have not found my particular case.
If you want to use the table in a query, you'd need to use the table operator
SELECT
COUNT(*)
INTO
var_ErrorCount
FROM
table( in_Errors );
That works. But it means that you're taking all of the data that you have in the PL/SQL collection, moving it to the SQL VM, doing the aggregation, and then returning the result to PL/SQL. It would likely be more efficient (and less code) in this case to just do
var_ErrorCount := in_Errors.count;

Resources