ORA-06550: line 1, column 7 (PL/SQL: Statement ignored) Error - sql
I am getting following error for the stored procedure and not able to understand the issue (must be from db side) While googling, I found similar issues but couldn't get the solution. Can any one help me please find the error in PROCEDURE ??
Error :-
18:58:50,281 ERROR [STDERR] java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'SP_DIST_RETAILER_REMAP'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Stored Prodedure(SP_DIST_RETAILER_REMAP) :-
CREATE OR REPLACE PROCEDURE SMAPRD02.SP_DIST_RETAILER_REMAP (
i_old_dist_code IN VARCHAR2,
i_new_dist_code IN VARCHAR2,
i_territory_remapping IN NUMBER,
i_remapping_reason IN VARCHAR2,
i_trans_doneby_rolename IN VARCHAR2,
i_trans_doneby_id IN NUMBER,
i_trans_dist_rolename IN VARCHAR2,
i_trans_ret_rolename IN VARCHAR2,
i_activity_type IN VARCHAR2,
i_ret_list IN V_ARRAY,
result OUT VARCHAR2,
i_o_query OUT VARCHAR2
)
AS
--i_ret_codes OUT VARCHAR2;
v_dist_count NUMBER;
v_ret_count NUMBER;
v_ret_codes VARCHAR2(10000) := '';
v_flag VARCHAR2(10) := 'true';
v_trans_id NUMBER;
v_query VARCHAR2(10000);
BEGIN
IF i_territory_remapping = 1 then
SELECT count(*) into v_dist_count FROM tblemployee where EMPCODE = i_new_dist_code and circle_code = (select emp.circle_code
from tblemployee emp where emp.empcode = i_old_dist_code) and upper(user_type) like upper('%dist%') and upper(ACCESS_TO) in ('SALES','BOTH') and upper(stage) not in (upper('InActive'));
ELSE
SELECT count(*) into v_dist_count FROM tblemployee where EMPCODE = i_new_dist_code and circle_code = (select emp.circle_code from tblemployee emp
where emp.empcode = i_old_dist_code) and cluster_code = (select emp.cluster_code from tblemployee emp where emp.empcode = i_old_dist_code)
and upper(user_type) like upper('%dist%') and upper(ACCESS_TO) in ('SALES','BOTH') and upper(stage) not in (upper('InActive'));
END IF;
IF v_dist_count =0 THEN
result := 'invalid_new_dist_code';
v_flag := 'false';
ELSIF v_dist_count = 1 THEN
SELECT count(*) into v_ret_count FROM tblretailer t where t.DIST_CODE = i_old_dist_code and (upper(t.ACCESS_TO) = 'SALES' or upper(t.ACCESS_TO) = 'BOTH');
--SELECT count(*) into v_ret_count FROM tblretailer t where t.DIST_CODE = i_old_dist_code and upper(t.ACCESS_TO) = 'SALES' and upper(t.stage) in ('APPROVED','INACTIVE');
IF v_ret_count=i_ret_list.count THEN
IF i_territory_remapping = 1 THEN
result := 'no_ret_left';
v_flag := 'false';
END IF;
ELSE
IF i_territory_remapping != 1 THEN
result := 'ret_left';
v_flag := 'false';
END IF;
END IF;
END IF;
IF i_ret_list is null or i_ret_list.count = 0 THEN
result := 'empty retailers list';
v_flag := 'false';
END IF;
/*FOR i IN i_ret_list.FIRST .. i_ret_list.LAST
LOOP
IF v_ret_codes is null
THEN
v_ret_codes := ''''||i_ret_list(i)||'''';
ELSE
v_ret_codes := v_ret_codes||','''||i_ret_list(i)||'''';
END IF;
IF v_ret_codes is null
THEN
v_ret_codes := i_ret_list(i);
ELSE
v_ret_codes := v_ret_codes||','||i_ret_list(i);
END IF;
END LOOP;
i_ret_codes := v_ret_codes;
v_flag := 'false';
result := 'success';*/
IF v_flag = 'true' THEN
FOR i IN i_ret_list.FIRST .. i_ret_list.LAST
LOOP
IF v_ret_codes is null
THEN
v_ret_codes := ''''||i_ret_list(i)||'''';
ELSE
v_ret_codes := v_ret_codes||','''||i_ret_list(i)||'''';
END IF;
END LOOP;
--i_ret_codes := v_ret_codes;
--update tblretailer set dist_code=i_new_dist_code,DIST_ID=to_number(i_new_dist_code),cluster_code=(select cluster_code from tblemployee where empcode = i_new_dist_code),FOSID='',FOS_CODE='',DSR_ID='',DSR_CODE='',LAST_UPDATED_DATE=sysdate where retcode in (v_ret_codes);
v_query := 'update tblretailer set dist_code='||i_new_dist_code||',DIST_ID=to_number('||i_new_dist_code||'),cluster_code=(select cluster_code from tblemployee where empcode = '||i_new_dist_code||'),FOSID='''',FOS_CODE='''',DSR_ID='''',DSR_CODE='''',LAST_UPDATED_DATE=sysdate where retcode in ('||v_ret_codes||')';
execute immediate (v_query);
--i_query :='update tblretailer set dist_code='||i_new_dist_code||',DIST_ID=to_number('||i_new_dist_code||'),cluster_code=(select cluster_code from tblemployee where empcode = '||i_new_dist_code||'),FOSID='',FOS_CODE='',DSR_ID='',DSR_CODE='',LAST_UPDATED_DATE=sysdate where retcode in ('||v_ret_codes||');';
insert into TBL_TRANSFER_SUP_MASTER(MASTER_ID,TRANS_ID,TRANS_DONEBY_ROLENAME,TRANS_DONEBY_ID,TRANS_FROM_ROLENAME,TRANS_FROM,TRANS_TO_ROLENAME,TRANS_TO,ACTIVITY_CODE,TRANS_DATE,TRANSFER_REASON,LAST_UPDATED_DATE)
values(SUP_MASTER_TRANS_ID_SEQ.nextval,SUP_MASTER_TRANS_ID_SEQ.nextval,i_trans_doneby_rolename,i_trans_doneby_id,i_trans_dist_rolename,i_old_dist_code,i_trans_dist_rolename,i_new_dist_code,'101',sysdate,i_remapping_reason,sysdate) return TRANS_ID into v_trans_id;
FOR i IN i_ret_list.FIRST .. i_ret_list.LAST
LOOP
insert into TBL_TRANSFER_SUP_DTLS(DTLS_ID,TRANS_ID,TRANS_ON_ROLENAME,TRANS_ON_ID,LAST_UPDATED_DATE)
values(SUP_DTLS_ID_SEQ.nextval,v_trans_id,i_trans_ret_rolename,i_ret_list(i),sysdate);
END LOOP;
IF SQL%ROWCOUNT>0 THEN
result := 'success';
ELSE
result := 'failure';
END IF;
--update tblstock set NEW_DIST_CODE_REMAP=i_new_dist_code,REMAP_DATE=sysdate,LAST_UPDATED_DATE=sysdate where (DIST_CODE=i_old_dist_code or NEW_DIST_CODE_REMAP=i_old_dist_code) and RET_CODE in (v_ret_codes);
v_query := 'update tblstock set NEW_DIST_CODE_REMAP='||i_new_dist_code||',REMAP_DATE=sysdate,LAST_UPDATED_DATE=sysdate where (DIST_CODE='||i_old_dist_code||' or NEW_DIST_CODE_REMAP='||i_old_dist_code||') and RET_CODE in ('||v_ret_codes||')';
execute immediate (v_query);
i_o_query := v_query;
insert all into TBL_ACTIVITY_LOG (LOG_ID,TRANS_ID,ACTIVITY_DONEBY_ROLENAME,ACTIVITY_DONEBY_ID,ACTIVITY_REFERENCE_ID,ACTIVITY_CODE,ACTIVITY_DATE)
values(ACTIVITY_LOG_TRANS_ID_SEQ.NEXTVAL,ACTIVITY_LOG_TRANS_ID_SEQ.NEXTVAL,i_trans_doneby_rolename,i_trans_doneby_id,v_trans_id,
act_code,sysdate) select log_config.ACTIVITY_CODE act_code from TBL_ACTIVITY_LOG_CONFIG log_config
where upper(log_config.ACTIVITY_TYPE)= upper(i_activity_type);
END IF;
END;
/
Java Code :-
try{
if(ret_list.size()>0)
ret_code = ret_list.toArray();
con = ConnectionManager.getDirectConnection();
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor(PropertyLoader.RET_SECONDARY_V_ARRAY,con);
ARRAY array_to_pass = new ARRAY( descriptor,con, ret_code );
cstmt = con.prepareCall("{ call SP_DIST_RETAILER_REMAP(?,?,?,?,?,?,?,?,?,?,?,?)}");
cstmt.setString(1,old_dist_code.trim());
cstmt.setString(2,new_dist_code.trim());
if(territory_remapping)
cstmt.setInt(3,1);
else
cstmt.setInt(3,2);
cstmt.setString(4,remapping_reason);
cstmt.setString(5,userVO.getRolename().trim());
cstmt.setInt(6,userVO.getEmpid());
cstmt.setString(7,PropertyLoader.DISTRIBUOTR_ROLENAME);
cstmt.setString(8,PropertyLoader.RETAILER_ROLENAME);
cstmt.setString(9,PropertyLoader.ACTIVITY_TYPES_RETAILER_REMAPPING);
cstmt.setArray(10,array_to_pass);
cstmt.registerOutParameter(11,Types.VARCHAR);
cstmt.registerOutParameter(12,Types.VARCHAR);
/*cstmt.registerOutParameter(13,Types.VARCHAR);*/
cstmt.execute();
status = cstmt.getString(11);
System.out.println("Remap Update Query "+cstmt.getString(12));
//System.out.println(cstmt.getString(13));
}
If the value stored in PropertyLoader.RET_SECONDARY_V_ARRAY is not "V_ARRAY", then you are using different types; even if they are declared identically (e.g. both are table of number) this will not work.
You're hitting this data type compatibility restriction:
You can assign a collection to a collection variable only if they have
the same data type. Having the same element type is not enough.
You're trying to call the procedure with a parameter that is a different type to the one it's expecting, which is what the error message is telling you.
The procedure which you are using is should be properly declared in the place which you are using it. For an example if it is under a user and in a package then it should be in that order. The username, package and procedurename.
Related
I am able to compile the code but it gives me an error of an sql command. How can I fix this?
I was able to write a section of code to delete a customer from the table given the customer email, unfortunately I am running into an error and do not know how to. I am beginner. Here is my code: CREATE OR REPLACE PROCEDURE DELETE_CUSTOMER(C_EMAIL IN VARCHAR2) IS CURSOR CUSTOMERS_CURSOR IS SELECT * FROM CUSTOMER WHERE CUSTOMER_OWNER_ID = C_EMAIL); V_ROW CUSTOMERS_CURSOR%ROWTYPE; DELETE_COUNT INTEGER := 0; BEGIN FOR V_ROW IN CUSTOMERS_CURSOR LOOP DELETE FROM CUSTOMER WHERE CUSTOMER_EMAIL = V_ROW.CUSTOMER_EMAIL; DELETE_CUSTOMER := DELETE_CUSTOMER + 1; END LOOP; IF DELETE_CUSTOMER = 0 THEN DBMS_OUTPUT.PUT_LINE('No customer has this email in our records thus ' || C_EMAIL || ', 0 rows deleted.'); ELSE DBMS_OUTPUT.PUT_LINE(DELETE_CUSTOMER || ' email deleted.'); END IF; END;
The error seems to tell you that there's an extra closing parenthesis on line 3, at the end of customers_cursor declaration. Just remove it. CREATE OR REPLACE PROCEDURE DELETE_CUSTOMER(C_EMAIL IN VARCHAR2) IS CURSOR CUSTOMERS_CURSOR IS SELECT * FROM CUSTOMER WHERE CUSTOMER_OWNER_ID = C_EMAIL; Also, lines with delete_customer variable seemed to be wrong.. maybe you are trying to refer to the delete_count variable? delete_count := delete_count + 1; IF delete_count = 0 THEN ... DBMS_OUTPUT.PUT_LINE(delete_count || ' email deleted.'); After fixing stuffs, your final procedure description should be like this: CREATE OR REPLACE PROCEDURE DELETE_CUSTOMER(C_EMAIL IN VARCHAR2) IS CURSOR CUSTOMERS_CURSOR IS SELECT * FROM CUSTOMER WHERE CUSTOMER_OWNER_ID = C_EMAIL; V_ROW CUSTOMERS_CURSOR%ROWTYPE; DELETE_COUNT INTEGER := 0; BEGIN FOR V_ROW IN CUSTOMERS_CURSOR LOOP DELETE FROM CUSTOMER WHERE CUSTOMER_EMAIL = V_ROW.CUSTOMER_EMAIL; DELETE_COUNT := DELETE_COUNT + 1; END LOOP; IF DELETE_COUNT = 0 THEN DBMS_OUTPUT.PUT_LINE('No customer has this email in our records thus ' || C_EMAIL || ', 0 rows deleted.'); ELSE DBMS_OUTPUT.PUT_LINE(DELETE_COUNT || ' email deleted.'); END IF; END;
PL/SQL Procedure Output
I'm having trouble correctly displaying the results of my procedure. When I execute the procedure that I created. The output should be 'FALSE' since DonorID: 303 has IDStatus = 20 and Paymonths = 0. However, I am getting 'TRUE.' Can someone please help? CREATE OR replace PROCEDURE ddpay_sp (donorid IN NUMBER, completed_pledge OUT BOOLEAN) IS CURSOR donor_cur IS SELECT idstatus, paymonths FROM dd_pledge WHERE iddonor = donorid; p_idstatus NUMBER(2); p_paymonths NUMBER(3); BEGIN OPEN donor_cur; LOOP FETCH donor_cur INTO p_idstatus, p_paymonths; EXIT WHEN donor_cur%NOTFOUND; IF p_idstatus = 20 AND p_paymonths = 0 THEN completed_pledge := FALSE; ELSE completed_pledge := TRUE; EXIT; END IF; END LOOP; CLOSE donor_cur; END ddpay_sp; DECLARE status BOOLEAN; BEGIN ddpay_sp(303, status); IF status = TRUE THEN dbms_output.put_line('TRUE'); ELSE dbms_output.put_line('FALSE'); END IF; END;
If you have multiple rows in your table that match iddonor = donorid, Oracle will loop through them until it finds one that doesn't match your p_idstatus = 20 AND p_paymonths = 0 condition and then exit from the loop with true, it will only return 'FALSE' if they all match on the second condition. If you have no rows that match iddonor = donorid, then your check will show 'FALSE' Demo You need to be clear what should happen when there are multiple rows in dd_pledge which have the input iddonor value. E.g. if you wish for it to return false if there are any matching rows which have idstatus=20 and paymonths=0 then you could make the loop exit on this condition instead: CREATE OR replace PROCEDURE ddpay_sp (donorid IN NUMBER, completed_pledge OUT BOOLEAN) IS CURSOR donor_cur IS SELECT idstatus, paymonths FROM dd_pledge WHERE iddonor = donorid; p_idstatus NUMBER(2); p_paymonths NUMBER(3); BEGIN OPEN donor_cur; LOOP FETCH donor_cur INTO p_idstatus, p_paymonths; EXIT WHEN donor_cur%NOTFOUND; IF p_idstatus = 20 AND p_paymonths = 0 THEN completed_pledge := FALSE; EXIT; ELSE completed_pledge := TRUE; END IF; END LOOP; CLOSE donor_cur; END ddpay_sp; / Demo showing the difference due to exit placement
Make the declared variable inside a trigger append its value if more than one condition is met
Well I was writing a trigger and I wanted that the declared variable v_message to append every time the condition is met. So for example if the first two statements are met the v_message should be something like "Invalid account Invalid amount". I must also find a way to separate these two messages by a space if the v_message already contains some sort of an error message as it wont be readable if you had something like this "Invalid accountInvalid amount". CREATE OR REPLACE TRIGGER checkPayments BEFORE INSERT ON tbl_payments FOR EACH ROW DECLARE v_message VARCHAR(100 CHAR); v_is_valid CHAR(1) := 'N'; BEGIN IF getActiveUser(getOrderUsername(:new.order_id)) = 0 THEN v_message := 'Invalid account'; ELSIF isValidAmount(:new.payment_amount) = 0 THEN v_message := 'Invalid amount'; ELSIF checkOrderExist(:new.order_id) = 0 THEN v_message := 'Invalid order ID'; ELSIF (getValidOrderPayments(:new.order_id) + :new.payment_amount ) > getOrderTotal(:new.order_id) THEN v_message := 'Payment exceeds total'; ELSE v_message := 'OK' ; v_is_valid := 'Y'; END IF; :new.payment_id:= seq_payment_id.nextval; :new.payment_date:= LOCALTIMESTAMP; :new.payment_message := v_message; :new.is_valid := v_is_valid; END; /
CREATE OR REPLACE TRIGGER checkPayments BEFORE INSERT ON tbl_payments FOR EACH ROW DECLARE v_message VARCHAR(100 CHAR); v_is_valid CHAR(1) := 'N'; BEGIN v_is_valid := 'Y'; IF getActiveUser(getOrderUsername(:new.order_id)) = 0 THEN v_message := 'Invalid account'; v_is_valid := 'N'; END IF; IF isValidAmount(:new.payment_amount) = 0 THEN v_message := v_message || ' Invalid amount'; v_is_valid := 'N'; END IF; IF checkOrderExist(:new.order_id) = 0 THEN v_message := v_message || ' Invalid order ID'; v_is_valid := 'N'; END IF; IF (getValidOrderPayments(:new.order_id) + :new.payment_amount ) > getOrderTotal(:new.order_id) THEN v_message := v_message || ' Payment exceeds total'; v_is_valid := 'N'; END IF; IF v_is_valid = 'Y' THEN v_message := 'OK' ; END IF; :new.payment_id:= seq_payment_id.nextval; :new.payment_date:= LOCALTIMESTAMP; :new.payment_message := trim(v_message); :new.is_valid := v_is_valid; END; /
use a validation function for an element in apex 5.0
I am trying to implement a validation on an application item in APEX 5.0. I am using a PL/SQL function returning a boolean begin if exists (select id_referencia from items where id_referencia = :P2_REFERENCIA) then return true; else return false; end if; end; When I submit my page, I get the following error ORA-06550: line 2, column 4: PLS-00204: function or pseudo-column 'EXISTS' may be used inside a SQL statement only ORA-06550: line 2, column 1: PL/SQL: Statement ignored
if exists isn't valid PL/SQL syntax. You could do a count(*) instead declare l_cnt integer; begin select count(*) into l_cnt from items where id_referencia = :P2_REFERENCIA; if( l_cnt >= 1 ) then return true; else return false; end if; end; If you really wanted to do an exists, you'd do something like this. I don't know why you'd want to do this assuming that id_referencia is the primary key of the table. But you could declare l_exists integer; begin begin select 1 into l_exists from dual where exists( select 1 from items where id_referencia = :P2_REFERENCIA ); exception when no_data_found then l_exists := 0; end; if( l_exists = 1 ) then return true; else return false; end if; end;
If you want to use EXISTS in a PL/SQL function returning BOOLEAN,try this DECLARE v_exist NUMBER; BEGIN SELECT 1 INTO v_exist FROM DUAL WHERE EXISTS (select id_referencia from items where id_referencia = :P2_REFERENCIA) IF v_exist IS NOT NULL THEN RETURN true; ELSE RETURN false; END IF; END;
Splitting two semicolons separated params
How to get two values from string in PL/SQL, like this: DECLARE context VARCHAR2(50) := 'param_a=Value1;param_b=Value2,Value3;'; paramA VARCHAR(50); paramB VARCHAR(50); BEGIN paramA = ... -- expected value: Value1 paramB = ... -- expected value: Value2,Value3 dbms_output.put_line(context); END;
You can use something like: DECLARE context VARCHAR2(50) := 'param_a=Value1;param_b=Value2,Value3;'; paramA VARCHAR(50); paramB VARCHAR(50); BEGIN paramA := SUBSTR('param_a=Value1;param_b=Value2,Value3;',instr('param_a=Value1;param_b=Value2,Value3;','=',1,1)+1,instr('param_a=Value1;param_b=Value2,Value3;',';',1,1)-instr('param_a=Value1;param_b=Value2,Value3;','=',1,1)-1); paramB := SUBSTR('param_a=Value1;param_b=Value2,Value3;',instr('param_a=Value1;param_b=Value2,Value3;','=',1,2)+1,instr('param_a=Value1;param_b=Value2,Value3;',';',1,2)-instr('param_a=Value1;param_b=Value2,Value3;','=',1,2)-1); dbms_output.put_line(paramA); dbms_output.put_line(paramb); END; Hope it Helps Vishad
DECLARE type TStrings IS TABLE OF VARCHAR2(4000); ltParams TStrings; ltParamsValue TStrings; function split(ivStr varchar2, ivDelim varchar2 := ',') return TStrings IS ltStrings TStrings; lvStr varchar2(4000); i number; BEGIN lvStr := ivStr; ltStrings := TStrings(); loop i := instr(lvStr, ivDelim); i := case when i = 0 and lvStr is not null then length(lvStr) else i end; exit when i = 0 or lvStr is null; ltStrings.extend(1); ltStrings(ltStrings.count) := rtrim(substr(lvStr, 1, i), ivDelim); lvStr := substr(lvStr, i + 1); end loop; RETURN ltStrings; END; BEGIN ltParams := split('param_a=Value1;param_b=Value2,Value3;', ';'); FOR idx IN ltParams.first .. ltParams.last LOOP ltParamsValue := split(ltParams(idx), '='); dbms_output.put_line(ltParamsValue(2)); END LOOP; end;
Hi Better way to do this kind of separation is by using REGEX(Regular Expressions). PLease try this code it may help plus it will reduce the coding length too. SET serveroutput ON; DECLARE context VARCHAR2(50) := 'param_a=Value1;param_b=Value2,Value3;'; paramA VARCHAR(50); paramB VARCHAR(50); BEGIN FOR rec IN (SELECT regexp_substr(context,'[^;"]+', 1, level) AS AV_TEST FROM dual CONNECT BY regexp_substr(context,'[^;"]+', 1, level) IS NOT NULL ) LOOP dbms_output.put_line(rec.av_test); END LOOP; END;