Exit handler exception in SAP HANA procedure - hana

In SAP HANA I tried to capture the error log in separate table but I can't...
This is my code:
create procedure "KABIL_PRACTICE"."PROC_ADV_SALES_INVENTORY"
(
IN "P_ID" integer,
IN "P_NAME" nvarchar(35),
IN "QTY" integer,
OUT Result "KABIL_PRACTICE"."TT_SALES_PRODUCT_INVENTORY")
LANGUAGE SQLSCRIPT
SQL SECURITY INVOKER
as begin LANGUAGE SQLSCRIPT
SQL SECURITY INVOKER
as begin
declare PROD_ID integer;
declare INV integer;
declare Q integer;
declare EP decimal (34,2);
declare SALES_AMOUNT Decimal(34,2);
select count(*) into PROD_ID from "KABIL_PRACTICE"."PRODUCT_ITEM_PROC" where "P_ID" = :P_ID;
select "Stock" into INV from "KABIL_PRACTICE"."PRODUCT_MASTER_PROC" where "P_ID" = :P_ID;
select "USP" into EP from "KABIL_PRACTICE"."PRODUCT_ITEM_PROC" where "P_ID" = :P_ID;
IF PROD_ID = 0 THEN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
insert into "KABIL_PRACTICE"."ERROR_LOG" values (::SQL_ERROR_CODE,::SQL_ERROR_MESSAGE);
select * from "KABIL_PRACTICE"."ERROR_LOG";
END;
ELSE IF INV >= :QTY THEN
SALES_AMOUNT := (:QTY * :EP);
insert into "KABIL_PRACTICE"."SALES_PROC" ("P_ID","P_NAME","QTY","Sales_AMount","Time_Of_Sale") values (:P_ID,:P_NAME,:QTY,:SALES_AMOUNT,CURRENT_TIMESTAMP);
update "KABIL_PRACTICE"."PRODUCT_MASTER_PROC" set "Stock" = "Stock"- :QTY where "P_ID" = :P_ID;
Result = select "S_ID","P_ID","P_NAME","QTY","Sales_AMount" from "KABIL_PRACTICE"."SALES_PROC";
END IF;
END IF;
end;
The same code for exit handler exception has worked in another procedure.
That is this code:
CREATE PROCEDURE "KABIL_PRACTICE"."EXCEPTION_EXAMPLE2" (
IN ip_id integer,
IN ip_name nvarchar(40),
OUT ex_message nvarchar(200) )
LANGUAGE SQLSCRIPT
SQL SECURITY INVOKER
AS
BEGIN
declare E integer;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
E := ::SQL_ERROR_CODE;
insert into "KABIL_PRACTICE"."ERROR_LOG" values
(:E,::SQL_ERROR_MESSAGE);
ex_message := 'SQL Exception occured. Error Code is: ' ||
::SQL_ERROR_CODE || ' Error message is: ' || ::SQL_ERROR_MESSAGE;
END;
INSERT INTO "KABIL_PRACTICE"."ERROR_TEST" VALUES( :ip_id, :ip_name);
ex_message := 'Product "' || :ip_id || '" inserted successfully';
END;
My doubt is: is my if condition correct or not... or the placement of that code is correct or not?

I think exception declaration just as parameter declarations should take place before SQL codes

Related

DB2 FUNCTION EXCEPTION

I'm converting Oracle plsql function into DB2 plsql function.Below I mentioned the structure of Oracle and DB2 query.
CREATE FUNCTION FUNCTION_NAME (IN PARAMETER1 DATATYPE)
Return varchar(4000) IS
N_COLUMN1 varchar(1);
N_COLUMN2 INT;
N_COLUMN3 VARCHAR(2000);
BEGIN
SELECT A.COLUMN1,A.COLUMN2 INTO N_COLUMN1,N_COLUMN2 FROM TABLE A WHERE A.COLUMN1=PARAMETER1;
IF N_COLUMN1 = 'A' then N_COLUMN3:= 'NEW_A';
ELSEIF N_COLUMN1 = 'B' then N_COLUMN3:= 'NEW_B';
END IF;
exception when others then N_COLUMN3:= 'OTHERS'
RETURN N_COLUMN3;
END;
/
DB2 query:
CREATE FUNCTION FUNCTION_NAME (IN PARAMETER1 DATATYPE)
Returns varchar(4000)
BEGIN
declare N_COLUMN1 varchar(1);
declare N_COLUMN2 INT;
declare N_COLUMN3 VARCHAR(2000);
SELECT A.COLUMN1,A.COLUMN2 INTO N_COLUMN1,N_COLUMN2 FROM TABLE A WHERE A.COLUMN1=PARAMETER1;
IF N_COLUMN1 = 'A' then set N_COLUMN3= 'NEW_A';
ELSEIF N_COLUMN1 = 'B' then set N_COLUMN3= 'NEW_B';
END IF;
exception when others then set N_COLUMN3= 'OTHERS'
RETURN N_COLUMN3;
END;
I'm getting error on Exception part.I searched over internet and i'm getting DECLARE type HANDLER FOR SQLEXCEPTION they provide this syntax and mentioned before execution part need to declare this one.i'm not sure what word i need to use in place of type.can anyone help me what is the equaivalent DB2 syntax for exception when others
This depends on where you want to pass the control in your code after the handler invocation.
Look at the handler-declaration description.
Below is a possible example of the function code.
CREATE FUNCTION FUNCTION_NAME
(
IN PARAMETER1 VARCHAR (1)
)
Returns varchar(4000)
BEGIN
declare N_COLUMN1 varchar(1);
declare N_COLUMN2 INT;
declare N_COLUMN3 VARCHAR(2000);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
-- The last statement executed in the function
-- when the handler fires.
-- The control is passed out of the function body
-- since the handler is declared
-- in the main BEGIN END function block.
RETURN 'OTHERS';
END;
SELECT A.COLUMN1,A.COLUMN2
INTO N_COLUMN1,N_COLUMN2
FROM
--TABLE A
(
VALUES
('A', 0)
, ('A', 0)
, ('B', 0)
) A (COLUMN1, COLUMN2)
WHERE A.COLUMN1=PARAMETER1;
IF N_COLUMN1 = 'A' then
set N_COLUMN3 = 'NEW_A';
ELSEIF N_COLUMN1 = 'B' then
set N_COLUMN3 = 'NEW_B';
END IF;
--exception when others then set N_COLUMN3= 'OTHERS'
RETURN N_COLUMN3;
END
SELECT P, FUNCTION_NAME (P) AS F
FROM (VALUES 'A', 'B') T (P)
P
F
A
OTHERS
B
NEW_B
fiddle

How do you call a Procedure in Block SQL

My procedure is below;
I have to create an anonymous block that CALLS the procedure and DISPLAYS all the customers total price and number of cars purchased from that PARTICULAR city
Can someone show me how to do this BLOCK
My procedure is as FOLLOW:
CREATE OR REPLACE PROCEDURE getCars
( v_custname OUT car.custname%TYPE,
v_purchcost OUT car.purchcost%TYPE,
v_city IN customer.custcity%TYPE,
v_count OUT NUMBER,
v_total OUT car.purchcost%TYPE
)
AS
BEGIN
Select c.custname, Count(c.custname), SUM(purchcost)
INTO v_custname, v_count, v_total
From car c
JOIN customer cs
ON c.custname = cs.custname
WHERE cs.custcity = v_city
Group By c.custname;
END;
/
This is what I have for the BLOCK to call procedure BUT ITS NOT WORKING
SET SERVEROUTPUT ON
SET VER OFF
ACCEPT p_city PROMPT 'Enter City Name: ';
DECLARE
CURSOR cname IS
Select customer.custname
INTO custname
From customer
Where UPPER(custcity) = UPPER('&p_city');
BEGIN
FOR
v_car in cname
LOOP
getCars(v_car.custname, v_count, v_total);
END LOOP;
DBMS_OUTPUT.PUT_LINE(v_car.custname||v_count||v_total);
END;
/
If you only want to display them the following can be done:
CREATE OR REPLACE PROCEDURE getcars (
v_city IN customer.custcity%TYPE
) AS
BEGIN
FOR c IN (
SELECT
car.custname,
COUNT(car.custname) count_custname,
SUM(purchcost) purchcost
FROM
car
JOIN customer cs ON car.custname = cs.custname
WHERE
cs.custcity = v_city
GROUP BY
car.custname
) LOOP
dbms_output.put_line('Customer '
|| c.custname
|| ' has bought '
|| c.count_custname
|| ' totaling '
|| purchcost);
END LOOP;
END;
Call the procedure:
DECLARE
v_city customer.custcity%TYPE := 'some city';
BEGIN
getcars(v_city);
END;
Otherwise if you need to return it for each customer then you should use cursors or more complicated data structures.

PL/SQL if table not exist create

Hello i use oracle SQL developer
I have create a procedure, and i need to check if a table exist, if not exist i must create how can do?
I have try this
DECLARE v_emp int:=0;
BEGIN
SELECT count(*) into v_emp FROM dba_tables;
if v_emp = 0 then
EXECUTE IMMEDIATE 'create table EMPLOYEE ( ID NUMBER(3), NAME VARCHAR2(30) NOT NULL)';
end if;
END;
but give me an error 00103 because not find table
Just execute the create and watch the exception if thrown. Oracle would never replace the DDL of a table.
declare
error_code NUMBER;
begin
EXECUTE IMMEDIATE 'CREATE TABLE EMPLOYEE(AGE INT)';
exception
when others then
error_code := SQLCODE;
if(error_code = -955)
then
dbms_output.put_line('Table exists already!');
else
dbms_output.put_line('Unknown error : '||SQLERRM);
end if;
end;
You can run this for example:
if (select count(*) from all_tables where table_name = 'yourTable')>0 then
-- table exists
else
-- table doesn't exist
end if;
You should try following,
declare
nCount NUMBER;
v_sql LONG;
begin
SELECT count(*) into nCount FROM dba_tables where table_name = 'EMPLOYEE';
IF(nCount <= 0)
THEN
v_sql:='
create table EMPLOYEE
(
ID NUMBER(3),
NAME VARCHAR2(30) NOT NULL
)';
execute immediate v_sql;
END IF;
end;

PL/SQL: ORA-00904: : invalid identifier

I am running the following SP but getting the error c1.pyid is invalid identifier. I am trying to use two different query results from one cursor. If there is any other way of using IF-else clause in a cursor, i am open to that too.
CREATE OR REPLACE
PROCEDURE FIX_DOCUMENT_RECORDS ( i_flag in varchar)
AS
Op_ID VARCHAR(8);
Op_Name VARCHAR(32);
skill VARCHAR(32);
temp_count VARCHAR(8);
temp_status VARCHAR(8):='Submitted';
QRYSTR VARCHAR2(400);
TYPE REF_CUR IS REF CURSOR;
c1 REF_CUR;
BEGIN
IF (i_flag='1') THEN
QRYSTR:='SELECT *
FROM dims_doc_master
WHERE concat_prod_id IS NULL
OR documenttypeid IS NULL
AND (pystatuswork = temp_status);';
ELSE
QRYSTR:='SELECT *
FROM dims_doc_master
WHERE (documentimageid IS NULL
AND p8id IS NULL)
AND (pystatuswork = temp_status);';
END IF;
open c1 FOR QRYSTR;
LOOP
BEGIN
DBMS_OUTPUT.PUT_LINE('loop begin');
UPDATE DIMS_DOC_MASTER
SET pystatuswork ='Cancelled',
documentstatus ='Cancelled',
cancellationdate='31-JAN-14',
cancelledbysid = c1.pxcreateoperator,
cancelreason ='Cancelled due to corruption.'
WHERE pyid =c1.pyid;
DBMS_OUTPUT.PUT_LINE('After updation'||c1.pyid );
--Begin PC_DOCUMENT UPDATION
UPDATE PC_DOCUMENT
SET pystatuswork ='Cancelled',
cancellationdate='31-JAN-14'
WHERE pyid =c1.pyid;
--Begin insert into History
--Select Operator name and ID
SELECT skill
INTO skill
FROM operator_map_skill
WHERE pyuseridentifier=c1.pxcreateoperator
AND rownum =1;
INSERT
INTO DIMS_DOC_HIST
(
DIMS_DOC_ID,
DOC_CHG_USR,
DOC_CHG_DT,
DOC_NEW_STS,
DOC_CHG_CMNT,
CRE_TS,
ROLE,
RSN_DESC,
TARGETROLE,
DOC_CHG_USR_ID,
DOC_ASG_USR_ID,
DOC_ASG_USR,
PREVSTATUS,
PREVSTATUSDT,
ASSIGNEDTODT,
TODISPLAY,
ACTIVITY_NAME
)
VALUES
(
c1.pyid,
'DIMS',
systimestamp,
'Cancelled',
'Cancelled due to corruption',
'31-JAN-14',
skill,
NULL,
skill,
c1.pxcreateoperator,
c1.pxcreateoperator,
c1.pxcreateopname,
'Submitted',
NULL,
systimestamp,
'Y',
'Updation through Script'
);
dbms_output.put_line
(
'Document ID= '||c1.pyid
)
;
SELECT COUNT(*)
INTO temp_count
FROM PC_ASSIGN_WORKBASKET
WHERE pxrefobjectinsname=c1.pyid;
IF(temp_count IS NOT NULL) THEN
DELETE FROM PC_ASSIGN_WORKBASKET WHERE pxrefobjectinsname=c1.pyid;
ELSE
DELETE FROM PC_ASSIGN_WORKLIST WHERE pxrefobjectinsname=c1.pyid;
END IF;
COMMIT;
END;
END LOOP;
CLOSE c1;
END;
You seem confusing cursor and fetched row.
In your current procedure: you open a cursor, do a loop (which looks to be endless since there is no EXIT statement), and after the loop you close the cursor (but it looks it will never happen)
To fetch results from a cursor, do the following:
CREATE OR REPLACE PROCEDURE ...
...
c1 REF_CUR;
ddm_record dims_doc_master%rowtype;
BEGIN
...
OPEN c1;
LOOP
FETCH c1 INTO ddm_record;
EXIT WHEN c1%NOTFOUND;
...
DBMS_OUTPUT.PUT_LINE('Document ID= ' || ddm_record.pyid); -- not c1.pyid
END LOOP;
CLOSE c1;
END;
/
Inspired from examples here: http://plsql-tutorial.com/plsql-explicit-cursors.htm
Try embedding the flag in your where clause:
open c1 FOR
SELECT *
FROM dims_doc_master
WHERE (i_flag='1' AND
(concat_prod_id IS NULL
OR documenttypeid IS NULL
AND (pystatuswork = temp_status))
OR (i_flag<>'1' AND
(documentimageid IS NULL
AND p8id IS NULL)
AND (pystatuswork = temp_status));
The logic can probably be simplified but logically that would work.

Getting an error in sql, when executing code below.How to declare a table type in plsql. Am a beginner . Please suggest

create or replace procedure BAS_NUM_UPD is
cursor cur is
select distinct o.oi_b,mpr.pa_ke_i,ltrim(substr(convert_171_to_711(cp.p_t_num),1,7),'0') bs_nbr
from t_obj o, mat_pa_rel mp, cor_pa cp
where o.ob_t = 'something'
and o.oi_b = mp.oi_b
and mp.pa_ke_i = cp.pa_ke_i;
l_ba_num_at_i number(10) := get_attribute_id('Ba timber');
flag1 VARCHAR2(10);
type t1 is table of varchar2(10);
par_k t1;
BEGIN
for x in cur loop
BEGIN
select pa_ke_i into par_k from mat_pa_rel where oi_b=x.oi_b ;
if par_k.count=null then
insert into cs_val (oi_b, at_i, value, flag, ) values (x.oi_b, l_ba_num_at_i, null, 1);
end if;
select flag into flag1 from cs_val where at_i = l_ba_num_at_i and oi_b = x.oi_b
and value = x.bs_nbr;
EXCEPTION
when NO_DATA_FOUND THEN
insert into cs_val (oi_b, at_i, value, flag, )
values (x.oi_b, l_ba_num_at_i, x.bs_nbr, 1);
flag1 :='Nothing';
when OTHERS
then
raise_application_error(-20011,'Unknown Exception in PROCEDURE');
END;
end loop;
end BAS_NUM_UPD;
error:
PLS-00642: local collection types not allowed in SQL statements
You should get it running if you do a bulk collect
select pa_ke_i bulk collect into par_k from mat_pa_rel where oi_b=x.oi_b ;
Then I think the if is not right. I think you need to do
if par_k.count = 0 then
But to be honest you might just make a count
select count(*) into l_cnt from mat_pa_rel where oi_b=x.oi_b;
If l_cnt = 0 then ...
Of course l_cnt has to be defined.
You should create type t1 in the schema and not in the pl/sql block.