Here is my procedure:
CREATE OR REPLACE PACKAGE shop_query_pkg IS
PROCEDURE shop_info_pp
(p_id IN bb_shopper.idshopper%TYPE,
p_firstname OUT bb_shopper.firstname%TYPE,
p_city OUT bb_shopper.city%TYPE,
p_state OUT bb_shopper.state%TYPE,
p_phone OUT bb_shopper.phone%TYPE,
p_email OUT bb_shopper.email%TYPE);
PROCEDURE shop_info_pp
(p_id IN bb_shopper.lastname%TYPE,
p_firstname OUT bb_shopper.firstname%TYPE,
p_city OUT bb_shopper.city%TYPE,
p_state OUT bb_shopper.state%TYPE,
p_phone OUT bb_shopper.phone%TYPE,
p_email OUT bb_shopper.email%TYPE);
END;
/
CREATE OR REPLACE PACKAGE BODY shop_query_pkg IS
PROCEDURE shop_info_pp
(p_id IN bb_shopper.idshopper%TYPE,
p_firstname OUT bb_shopper.firstname%TYPE,
p_city OUT bb_shopper.city%TYPE,
p_state OUT bb_shopper.state%TYPE,
p_phone OUT bb_shopper.phone%TYPE,
p_email OUT bb_shopper.email%TYPE)
IS
BEGIN
SELECT firstname, city, state, phone, email
INTO p_firstname, p_city, p_state, p_phone, p_email
FROM bb_shopper
WHERE idshopper = p_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('ID does not exist');
END;
PROCEDURE shop_info_pp
(p_id IN bb_shopper.lastname%TYPE,
p_firstname OUT bb_shopper.firstname%TYPE,
p_city OUT bb_shopper.city%TYPE,
p_state OUT bb_shopper.state%TYPE,
p_phone OUT bb_shopper.phone%TYPE,
p_email OUT bb_shopper.email%TYPE)
IS
BEGIN
SELECT firstname, city, state, phone, email
INTO p_firstname, p_city, p_state, p_phone, p_email
FROM bb_shopper
WHERE lastname = p_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Last name does not exist');
END;
END;
However when I try to execute my procedure using this code:
VARIABLE g_fname VARCHAR2
VARIABLE g_city VARCHAR2
VARIABLE g_state VARCHAR2
VARIABLE g_phone VARCHAR2
VARIABLE g_email VARCHAR2
EXECUTE shop_query_pkg.shop_info_pp(23, :g_fname, :g_city, :g_state, :g_phone, :g_email);
PRINT :g_fname
PRINT :g_city
PRINT :g_state
PRINT :g_phone
PRINT :g_email
I get this error message:
BEGIN shop_query_pkg.shop_info_pp(23, :g_fname, :g_city, :g_state, :g_phone, :g_email); END;
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "S36.SHOP_QUERY_PKG", line 11
ORA-06512: at line 1
I think it something wrong with my select statement, but I keep checking it and I can't figure out what's wrong with it.
Here is the DESC bb_shopper:
Name Null? Type
IDSHOPPER NOT NULL NUMBER(4)
FIRSTNAME VARCHAR2(15)
LASTNAME VARCHAR2(20)
ADDRESS VARCHAR2(40)
CITY VARCHAR2(20)
STATE CHAR(2)
ZIPCODE VARCHAR2(15)
PHONE VARCHAR2(10)
FAX VARCHAR2(10)
EMAIL VARCHAR2(25)
USERNAME VARCHAR2(8)
PASSWORD VARCHAR2(8)
COOKIE NUMBER(4)
DTENTERED DATE
PROVINCE VARCHAR2(15)
COUNTRY VARCHAR2(15)
PROMO CHAR(1)
Yes I've tried changing state to CHAR and I get the same message.
You must fully specify the VARIABLE types and add the maximum varchar2 sizes.
If you use the following block, it works as expected:
VARIABLE g_fname VARCHAR2(60)
VARIABLE g_city VARCHAR2(60)
VARIABLE g_state VARCHAR2(60)
VARIABLE g_phone VARCHAR2(60)
VARIABLE g_email VARCHAR2(60)
EXECUTE shop_query_pkg.shop_info_pp(23, :g_fname, :g_city, :g_state, :g_phone, :g_email);
PRINT :g_fname
PRINT :g_city
PRINT :g_state
PRINT :g_phone
PRINT :g_email
Related
I am using Toad For Oracle and I have a procedure in a package where I'm getting the CLOB value for result. I'll be using dummy variables only but I'll be putting the whole process here.
My goal is to a rest web service where my output will be a JSON CLOB.
START OF THE BODY PACKAGE
TYPE in_emp_type IS RECORD ( emp_id NUMBER,
emp_fname VARCHAR2(50), emp_lname VARCHAR2(50),
city VARCHAR2(40), country(50) )
in_emp_rec in_emp_type ;
TYPE out_emp_type IS RECORD (emp_addr_1 VARCHAR2(100), emp_addr_2 VARCHAR2(100);
TYPE out_emp_tab_type IS TABLE OF out_emp_type;
query_tab out_emp_tab_type := out_emp_tab_type ();
PROCEDURE get_employee_details(api_key VARCHAR2, emp_id NUMBER,
emp_fname VARCHAR2, emp_lname VARCHAR2, out_result_json OUT CLOB ) IS
CURSOR get_all_emp IS
select city, country from emp_table
where emp_id = emp_id
and fname = emp_fname
and lname = emp_lname ;
CURSOR get_emp_addr (emp_id NUMBER, city VARCHAR2) IS
select addr_1, addr_2 from emp_addr
where emp_id = emp_id and city = city;
v_city VARCHAR2;
v_country VARCHAR2;
v_json_input CLOB;
v_result_json CLOB;
BEGIN
open get_all_emp;
fetch get_all_emp into v_city , v_country ;
close get_all_emp;
v_json_input := '{"EmployeeDetails":
{"EmployeeID": || emp_id || ' ",
"EmployeeFirstName": || emp_fname || '",
"EmployeeLastName": || emp_lname || '",
"EmployeeCity": || v_city || '",
"EmployeeCountry": || v_country || '"}'
convert_input_json(v_json_input,in_emp_rec);
open get_emp_addr (emp_id, city);
fetch get_emp_addr bulk collect into query_tab ;
v_result_json := convert_result_json(query_tab);
out_result_json := v_result_json;
END;
And this is my sample of the convert_input_json procedures & convert_result_json function
PROCEDURE convert_input_json(input_json IN CLOB, output_json OUT in_emp_type) IS
CURSOR get_details IS
select emp_id, emp_fname, emp_lname, city, country
from json_table(input_json, '$' COLUMNS (
emp_id NUMBER PATH '$.EmployeeDetails.EmployeeID',
emp_fname VARCHAR2(50) PATH '$.EmployeeDetails.EmployeeFirstName',
emp_lname VARCHAR2(50) PATH '$.EmployeeDetails.EmployeeLastName', ... includeother fields here)
BEGIN
output_json := in_emp_type( emp_id => NULL, emp_fname => NULL....)
open get_details;
fetch get_details into output_json.emp_id , output_json.emp_fname ....);
close get_details;
END;
FUNCTION convert_result_json (in_result out_emp_tab_type) RETURN CLOB IS
v_clob CLOB
BEGIN
FOR i in 1...query_tab.count LOOP
v_clob := '{ '||chr(13)||'"customerResults": {'
v_clob := v_clob||chr(13)||chr(9)||chr(9)||'"addr1": "'||query_tab(i).emp_addr_1 ||'",';
v_clob := v_clob||chr(13)||chr(9)||chr(9)||'"addr2": "'||query_tab(i).emp_addr_2 ||'",';
END LOOP;
RETURN (v_clob)
END;
So when I try to run this, I'm getting the ORA-06502: PL/SQL: numeric or value error: character string buffer too small
And I'm not really sure why am I getting this error. Can someone please help me.
There should be an error stack trace showing the line number that raised the exception. Looking at your code, there are two obvious places where this can happen:
The JSON_TABLE COLUMNS mapping - ensure that emp_fname/emp_lname never overflows the allotted 50 characters.
In the convert_result_json function, you are using || to append new addresses to an existing CLOB value. || will convert the operands to varchar2(32767). If the size of the CLOB + the new string being appended > 32KB, it will fail due to the varchar2 datatype limit. If this is your issue, use dbms_lob to append to your LOBs, not ||.
CREATE TABLE Docente
(
opcion varchar2(10),
id_Docente NUMBER,
nombre VARCHAR2(30),
apellido VARCHAR2(30),
cedula NUMBER,
titulo VARCHAR2(100),
observaciones VARCHAR2(200),
estado VARCHAR2(10),
mensaje varchar2(50) NULL,
CONSTRAINT PK_Docente PRIMARY KEY (id_Docente)
);
CREATE OR REPLACE PROCEDURE sp_crud_docente(
p_opcion varchar2,
p_id_Docente NUMBER,
p_nombre VARCHAR2,
p_apellido VARCHAR2,
p_cedula NUMBER,
p_titulo VARCHAR2,
p_observaciones VARCHAR2,
p_estado VARCHAR2,
p_mensaje out varchar2)
as
v_valor int;
v_row Docente%rowtype;
begin
if (p_opcion = 'I') then
begin
Select MAX(id_Docente)+ 1 into v_valor from Docente;
if v_valor is null then
v_valor := 1;
p_mensaje:= 'Registro inserted...';
DBMS_OUTPUT.PUT_LINE(p_mensaje);
insert into Docente
values (p_opcion,v_valor,p_id_Docente,p_nombre,p_apellido,p_cedula,p_titulo,p_observaciones,p_estado);
end if;
end;
else if (p_opcion = 'U') then
update Docente set opcion=p_opcion,
id_Docente=p_id_Docente,
nombre=p_nombre,
apellido=p_apellido,
cedula=p_cedula,
titulo=p_titulo,
observaciones=p_observaciones,
estado=p_estado
where id_Docente=p_id_Docente;
p_mensaje:= 'Registro updated...';
DBMS_OUTPUT.PUT_LINE(p_mensaje);
else if (p_opcion = 'S') then
begin
Select
opcion,
id_Docente,
nombre,
apellido,
cedula,
titulo,
observaciones,
estado,
mensaje
into v_row
from Docente;
p_mensaje := ('Ok');
DBMS_OUTPUT.PUT_LINE(p_mensaje||' --> '||v_row.opcion||'|'||v_row.id_Docente||'|'||v_row.nombre||'|'||v_row.apellido||'|'||v_row.cedula||'|'||v_row.titulo||'|'||v_row.observaciones||'|'||v_row.estado||'|'||v_row.mensaje);
end;
else if (p_opcion = 'D') then
Delete from Docente where id_Docente=p_id_Docente;
p_mensaje := ('Proceso ejecutado correctamente');
DBMS_OUTPUT.PUT_LINE(p_mensaje);
commit;
end if;
end if;
end if;
end if;
EXCEPTION
WHEN OTHERS then
p_mensaje := ('ERROR. No se pudo ejecutar el proceso');
rollback;
end;
Take out the length of the incoming parameters:
create or replace procedure sp_crud_docente (
p_opcion varchar2,
p_id_Docente NUMBER,
p_nombre VARCHAR2,
p_apellido VARCHAR2,
p_cedula NUMBER,
p_titulo VARCHAR2,
p_observaciones VARCHAR2,
p_estado VARCHAR2,
p_mensaje out varchar2)
See 8.7.1 Formal and Actual Subprogram Parameters section of the 19c manual "Database PL/SQL Language Reference"
Bobby
Apart from the fact that varchar2 parameters can't have size, this is practically unsolvable without you posting the docente table description.
Bad habits kick; you're wrongly relying on the fact that you know what you're doing, but it turns out you don't.
I can't figure out how many nor which columns docente contains, and in which order.
insert into docente should explicitly mention all columns you're inserting into, one-by-one. Code you wrote suggests that table contains 9 columns (opcion, id_docente, nombre, apellido, cedula, titulo, observaciones, estado).
update, on the other hand, updates only 6 of them (nombre, apellido, cedula, tutlo, observaciones, estado) which doesn't collide with insert; it is OK if you don't update all columns.
However, p_opcion = 'S' selects only 7 columns into v_row which is declared as docente%rowtype. Out of those 7 columns, I believe you "forgot" a comma between id_docente and nombre - those are two columns, it's not that nombre is id_docente's alias, right? Suppose it is 8 columns that are selected after all. Now, that collides with number of columns you used in insert (9 of them). If you're selecting into %rowtype, you must select ALL columns in EXACT ORDER.
I suggest you review code you wrote, pay attention about what I said and fix those errors.
Stored procedure is not returning the value that I am expecting. I did not know what is the problem with the procedure.
Here is the procedure:
CREATE OR REPLACE procedure PRC_CUSTOMER_WITH_LOGIN
(p_name_out out varchar2,
p_count out int,
p_all_records out SYS_REFCURSOR,
p_mode in varchar2,
p_id in varchar2,
p_name_in in varchar2,
p_contact_no in varchar2,
p_email in varchar2,
p_address in varchar2)
IS
BEGIN
IF p_mode='q'
THEN
select NAME into p_name_out from customer where id='1';
ELSIF p_mode='i'
THEN
INSERT into customer(id,name,contactNo,email,address)
Values(p_id, p_name_in, p_contact_no , p_email , p_address);
ELSIF p_mode='u'
THEN
UPDATE customer set name=p_name_in, contactNo=p_contact_no, email=p_email, address=p_address
where id=p_id;
ELSIF p_mode='d'
THEN
DELETE from customer where id=p_id;
ELSIF p_mode='a'
THEN
OPEN p_all_records FOR
select * from customer;
ELSIF p_mode='l'
THEN
SELECT COUNT(*) into p_count from customer WHERE name=p_name_in AND id=p_id;
END IF;
END;
/
This is the procedure all other conditions are working fine but the last condition is not working correctly this condition return 0 all the time whether I enter the correct id and name or wrong.
Here I am calling this procedure
cs = (OracleCallableStatement) con.prepareCall("{call TESTDB.PRC_CUSTOMER_WITH_LOGIN(?,?,?,?,?,?,null,null,null)}");
cs.registerOutParameter(1, OracleTypes.VARCHAR);
cs.registerOutParameter(2, OracleTypes.INTEGER);
cs.registerOutParameter(3, OracleTypes.CURSOR);
cs.setString(4, "l");
cs.setString(5, password);
cs.setString(6, name);
cs.executeQuery();
chk=cs.getInt(2);
System.out.println(chk);
Can someone tell me what the mistake is that I'm making here? I shall be thankful .... :)
Try to use UPPER both side so if any case sensitive names are there then it will nullify it.
SELECT COUNT(*) into p_count from customer WHERE upper(name)=upper(p_name_in) AND id=p_id;
Maybe you are wrong when you set id with the password value?
1-> p_name_out out varchar2,
2-> p_count out int,
3-> p_all_records out SYS_REFCURSOR,
4-> p_mode in varchar2,
5-> p_id in varchar2, --- 5 is id, not password ??!?
6-> p_name_in in varchar2,
p_contact_no in varchar2,
p_email in varchar2,
p_address in varchar2
cs = (OracleCallableStatement) con.prepareCall(
"{call TESTDB.PRC_CUSTOMER_WITH_LOGIN(?,?,?,?,?,?,null,null,null)}");
cs.registerOutParameter(1, OracleTypes.VARCHAR);
cs.registerOutParameter(2, OracleTypes.INTEGER);
cs.registerOutParameter(3, OracleTypes.CURSOR);
cs.setString(4, "l");
cs.setString(5, password);
cs.setString(6, name);
Another possibility is your id/password is stored as encrypted thing?
I define a new type in sql oracle and define a static procedure.
CREATE OR REPLACE TYPE address AS OBJECT(
house_no VARCHAR2 (10),
street VARCHAR2 (30),
city VARCHAR2 (20),
state VARCHAR2 (10),
pincode VARCHAR2 (10),
STATIC PROCEDURE new_address (house_no VARCHAR2,
street VARCHAR2,
city VARCHAR2,
state VARCHAR2,
pincode VARCHAR2)
);
CREATE OR REPLACE TYPE BODY address
AS
STATIC PROCEDURE new_address (house_no VARCHAR2,
street VARCHAR2,
city VARCHAR2,
state VARCHAR2,
pincode VARCHAR2)
IS
sqlstmt VARCHAR (100);
BEGIN
sqlstmt :=
'insert into university.user_address values(address(:name, :name, :name, :name, :name, :name))';
EXECUTE IMMEDIATE sqlstmt
USING house_no,
street,
city,
state,
pincode;
END;
END;
When I called the function user_address it shows error: not all variables bound.
CREATE TABLE user_address OF address
begin
UNIVERSITY.address.new_address('123', 'nazar', 'isfahan','isfahan','9893');
END;
I changed implementing like this (edit sqlstmt with numbers) , but it shows error again.
sqlstmt :=
'insert into university.user_address values(address(:1, :2, :3, :4, :5, :6))';
How do I fix it?
Below line have 6 bind variables where as execute immediate only have 5.
sqlstmt :=
'insert into university.user_address values(address(:name, :name, :name, :name, :name, :name))';
CREATE or REPLACE PROCEDURE SP_INSERT_OVERSEAS_COMPANY
(
COMPANY_CODE IN NUMBER,
COMPANY_NAME IN VARCHAR2,
STREET_ADDR IN VARCHAR2,
COMPANY_STATE IN VARCHAR2,
ZIP_CODE IN VARCHAR2,
COUNTRY IN VARCHAR2,
CONTACT_PERSON IN VARCHAR2,
CONTACT_NUMBER IN VARCHAR2
)
AS
BEGIN
IF sysdate between trunc(sysdate,'DD')+interval '9' hour and trunc(sysdate,'DD')+interval '17' hour
THEN
INSERT INTO Overseas_Company
VALUES
(COMPANY_NAME,COMPANY_NAME,STREET_ADDR,COMPANY_STATE,ZIP_CODE,COUNTRY,CONTACT_PERSON,CONTACT_NUMBER);
ELSE
dbms_output.put_line ('Process is outside of normally working hours');
END IF;
END SP_INSERT_OVERSEAS_COMPANY;
/
Should COMPANY_NAME,COMPANY_NAME,... be COMPANY_CODE,COMPANY_NAME,...? The parameter COMPANY_CODE is not used in the procedure. Are you getting numeric conversion errors?