ORA-24344: success with compilation error when trying to implement holt winter procedure - oracle

I'm getting the ORA-24344: success with compilation error whenever i try to import an application(that works on my database) to the oracle apex cloud or any other local cloud, the same error appears ORA-24344: success with compilation but when i run the application it runs but this procedure (holt_winters) does not run, no errors it just doesn't do anything.
here is my code. its a holt winters prediction method for those of you who're interested.
any help would be apperciated
create or replace PROCEDURE "HOLT_WINTERS" (report_id_in IN INTEGER
, alpha IN VARCHAR2
, beta IN VARCHAR2
, gamma IN VARCHAR2
, prediction_step IN VARCHAR2
, seasonality IN VARCHAR2
, from_date IN varchar2
, to_date IN varchar2
, FDEW_ID IN integer) AS
BEGIN
begin
-- delete previous settings
delete from demo_ts_settings where report_id_in > 0;
-- select ESM as the algorithm
insert into demo_ts_settings
values (dbms_data_mining.algo_name,
dbms_data_mining.algo_exponential_smoothing);
-- set ESM model to be Holt-Winters Seasonal Adjusted
insert into demo_ts_settings
values (dbms_data_mining.exsm_model,
dbms_data_mining.exsm_HW_ADDSEA);
-- set interval to be month
insert into demo_ts_settings
values (dbms_data_mining.exsm_interval,
dbms_data_mining.exsm_interval_month);
-- set prediction to 4 steps ahead
insert into demo_ts_settings
values (dbms_data_mining.exsm_prediction_step,
prediction_step);
-- set seasonal cycle to be 5 quarters
insert into demo_ts_settings
values (dbms_data_mining.exsm_seasonality,
seasonality);
BEGIN
dbms_data_mining.drop_model('DEMO_TS_MODEL_' || report_id_in);
EXCEPTION
WHEN others THEN null;
END;
EXECUTE IMMEDIATE 'create view holt_winters_temp_table_'||report_id_in|| ' as select RATES.*
from RATES
where (DATE_OF_RECORD between to_date('''|| from_date ||''', ''YYYY-MM-DD'') ' ||
'and to_date('''||to_date||''', ''YYYY-MM-DD'') )
and STATUS = ''FALSE''
and report_id ='|| report_id_in;
dbms_data_mining.create_model(model_name => 'DEMO_TS_MODEL_' || report_id_in,
mining_function => 'TIME_SERIES',
data_table_name => 'holt_winters_temp_table_' || report_id_in,
case_id_column_name => 'date_of_record',
target_column_name => 'VAL',
settings_table_name => 'DEMO_TS_SETTINGS');
BEGIN
FOR i IN 1..5
LOOP
BEGIN
sys.DBMS_SESSION.sleep(20);
INSERT_HOLT_HISTORY('DM$PPDEMO_TS_MODEL_' || report_id_in);
COMMIT;
EXIT;
EXCEPTION
WHEN others THEN null;
DBMS_OUTPUT.PUT_LINE (SQLCODE || ' ' || SQLERRM);
END; -- sub-block ends
END LOOP;
END;
end;
END HOLT_WINTERS;

Related

PL/SQL procedure stuck

I have the following scenario:
Java servlet calls PL/SQL procedure and waits for return value.
The PL/SQL procedure calls other PL/SQL procedures that do a series of updates, inserts and commits. When everything completes the initial PL/SQL procedure writes a log using pragma and returns 1 if successful.
The problem is that on one environment everything works fine and on another environment the PL/SQL procedure remains stuck(same code and data on both environments).
PL/SQL procedure ex:
PROCEDURE Export_1511_PDH_Physic ( o_ErrorCode OUT NUMBER,
o_ErrorText OUT VARCHAR2,
o_Resultat OUT NUMBER) is
GlobalExportID NUMBER;
BEGIN
ASYNCLOG ('Export_1511_PDH_Physic', 'Started');--Pragma writing logs
GlobalExportID :=0;
o_Resultat := 0;
select nvl(max(exportid),0) into GlobalExportID from async.MaxNodeList;
GlobalExportID := GlobalExportID + 1;
upd_JRLExport('1511Max Export', GlobalExportID, 0);--Pragma writing logs
pkggato.MaxIRM_DoExport(GlobalExportID); ---more pl/sql procedures(update, insert...)
o_Resultat := o_Resultat+1;
Everithing printed ok below.
pkgdebug.writelog('o_ErrorCode - ' || o_ErrorCode,'Info');
pkgdebug.writelog('o_ErrorTex - ' || o_ErrorText,'Info');
pkgdebug.writelog('o_Resultat - ' || o_Resultat,'Info');
The below logs are printed fine.
ASYNCLOG ('Export_1511_PDH_Physic', 'Finished'); --Pragma writing logs
upd_JRLExport('1511Max Export', GlobalExportID, 1); --Pragma writing logs
END;
If a do a DB restart everything works fine on the 1st run.
Any idea on how to debug this?
PROCEDURE upd_JRLExport(pis_export_type ASYNC_JRLEXPORT.EXPORTTYPE%TYPE,
pin_export_no ASYNC_JRLEXPORT.NO_EXPORT%TYPE,
pin_start_end_flg NUMBER, --0: Start / 1: End
pin_status ASYNC_JRLEXPORT.STATUS%TYPE DEFAULT NULL)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
ld_now DATE;
BEGIN
SELECT SYSDATE
INTO ld_now
FROM DUAL;
UPDATE ASYNC_JRLEXPORT
SET START_DATE = DECODE(pin_start_end_flg, 0, ld_now, START_DATE),
END_DATE = DECODE(pin_start_end_flg, 1, ld_now, END_DATE),
NO_EXPORT = NVL(pin_export_no, NO_EXPORT),
STATUS = NVL(pin_status, STATUS)
WHERE EXPORTTYPE = pis_export_type;
COMMIT;
END upd_JRLExport;
Thanks,
Catalin.
PROCEDURE upd_JRLExport(pis_export_type ASYNC_JRLEXPORT.EXPORTTYPE%TYPE,
pin_export_no ASYNC_JRLEXPORT.NO_EXPORT%TYPE,
pin_start_end_flg NUMBER, --0: Start / 1: End
pin_status ASYNC_JRLEXPORT.STATUS%TYPE DEFAULT NULL)
IS
V_ERRORMESSAGE varchar2(2000);
PRAGMA AUTONOMOUS_TRANSACTION;
ld_now DATE;
BEGIN
SELECT SYSDATE
INTO ld_now
FROM DUAL;
UPDATE ASYNC_JRLEXPORT
SET START_DATE = DECODE(pin_start_end_flg, 0, ld_now, START_DATE),
END_DATE = DECODE(pin_start_end_flg, 1, ld_now, END_DATE),
NO_EXPORT = NVL(pin_export_no, NO_EXPORT),
STATUS = NVL(pin_status, STATUS)
WHERE EXPORTTYPE = pis_export_type;
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
V_ERRORMESSAGE := SQLERRM;
dbms_output.put_line('NO DATA FOUND :' || V_ERRORMESSAGE);
RAISE;
WHEN OTHERS
THEN
V_ERRORMESSAGE := SQLERRM;
dbms_output.put_line('OTHER ERROR :' || V_ERRORMESSAGE);
RAISE;
END upd_JRLExport;

Trigger, at line 1 ORA 04098

Hi im setting up some triggers and i cant get past this error
SET SERVEROUTPUT ON
CREATE OR REPLACE TRIGGER trigger2
BEFORE INSERT ON new_donation
FOR EACH ROW
--WHEN (new.contamt <= 10)
DECLARE
v_idno VARCHAR2(5);
v_driveno VARCHAR2(3);
v_contdate DATE;
v_contamt NUMBER(6,2);
BEGIN
SELECT IDNO, DRIVENO, CONTDATE, CONTAMT INTO v_idno, v_driveno, v_contdate, v_contamt
FROM OLD_DONATION2
WHERE IDNO = :new.idno;
IF :new.contamt < 50 THEN
RAISE_APPLICATION_ERROR (-20001, 'CONTRIBUTION TOO LOW FOR '
|| :new.idno || ' ' || :new.contamt);
END IF;
END;
/
SET SERVEROUTPUT OFF
another part
DECLARE
v_idno new_donation.idno%TYPE := '&in_idno';
v_driveno new_donation.driveno%TYPE := '&in_driveno';
v_contdate new_donation.contdate%TYPE := '&in_contdate';
v_contamt new_donation.contamt%TYPE := &in_contamt;
BEGIN
INSERT INTO new_donation
VALUES (v_idno, v_driveno, v_contdate, v_contamt);
END;
/
Im getting this error when I insert values at trigger2.
ERROR at line 1: ORA-04098: trigger 'XXXXXXXXX.NEW_DONATION' is
invalid and failed re-validation ORA-06512: at line 7
All im trying to do is insert some values input by the user to this new table, which is empty.
Also when donation amount is < 10 I want a error out.
Follow these steps.
Run this query select status from all_objects where object_name = 'TBL_USER_TRIGGER' and object_type = 'TRIGGER';
If the status is invalid run alter trigger trigger2 compile;
Then run show errors
It will throw the errors for you. You need to fix those.

plsql stored procedure syntax error

when I try the following code, I get a procedure completed with 0 compilation errors.. message instead of procedure successfully completed message.
what's wrong with this? and help me in correcting this error
CREATE OR REPLACE PROCEDURE omar_manager_report1 (
pi_co_id IN VARCHAR2, -- Company ID
pi_cntr_nbr IN NUMBER DEFAULT 0,
-- if Contract number is passed then Case 1: will be executed
pi_overdue_days IN NUMBER DEFAULT 0,
--No of days related to Over due of application passed.
po_var_ref OUT sys_refcursor
)
IS
lv_query VARCHAR2(400) ;
lv_co_id VARCHAR2 (200);
BEGIN
lv_co_id := REPLACE (pi_co_id, ',', ''',''');
--Default option for all group office
lv_query :=
'select distinct gue.co_id,
(SELECT event_descp FROM get_event WHERE co_id = gue.co_id AND event_cd = gue.event_cd) AS event_desc
FROM get_uwtg_event gue';
DBMS_OUTPUT.put_line ('lv_query');
OPEN po_var_ref FOR lv_query;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLCODE);
END;
/
Executing a CREATE OR REPLACE PROCEDURE... statement compiles the procedure, but it does not call the procedure. You'll need to write a PL/SQL block similar to the following to invoke your procedure:
DECLARE
csrOut SYS_REFCURSOR;
BEGIN
omar_manager_report1(pi_co_id => '123456',
pi_cntr_nbr => 0,
pi_overdue_days => 0,
po_var_ref => csrOut);
-- Add code here to fetch from csrOut and use the results appropriately
-- Close the cursor opened by omar_manager_report1
CLOSE csrOut;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Exception: ' || SQLCODE || ' : ' || SQLERRM);
END;
Best of luck.

Output results from Oracle Ref cursor

How can i rewrite below pl/sql block in order to avoid hard code column names one by one ? Below data are from OE schema. For orders table there are 8 columns on this table. Is it possible to output the results without hard code column names ? Any help is appreciated.
create or replace PACKAGE show_details AS
TYPE rt_order IS REF CURSOR RETURN orders%ROWTYPE;
TYPE typ_cust_rec IS RECORD
(cust_id NUMBER(6), cust_name VARCHAR2(20),
custphone customers.phone_numbers%TYPE,
credit NUMBER(9,2), cust_email VARCHAR2(30));
TYPE rt_cust IS REF CURSOR RETURN typ_cust_rec;
--Get order detail
PROCEDURE get_order(p_orderid IN NUMBER, p_cv_order IN OUT rt_order);
--Get customer detail
PROCEDURE get_cust(p_custid IN NUMBER, p_cv_cust IN OUT rt_cust);
END show_details;
create or replace PACKAGE BODY show_details
AS
PROCEDURE get_order (p_orderid IN NUMBER, p_cv_order IN OUT rt_order)
IS
BEGIN
OPEN p_cv_order FOR
SELECT * FROM orders
WHERE order_id = p_orderid;
-- CLOSE p_cv_order
END get_order;
PROCEDURE get_cust (p_custid IN NUMBER, p_cv_cust IN OUT rt_cust)
IS
BEGIN
OPEN p_cv_cust FOR
SELECT customer_id, cust_first_name,phone_numbers,
credit_limit,cust_email FROM customers WHERE customer_id = p_custid;
-- CLOSE p_cv_cust
END get_cust;
END;
SET SERVEROUTPUT ON SIZE UNLIMITED;
declare
cur_orders show_details.rt_order;
v_ordertab cur_orders%ROWTYPE;
begin
show_details.get_order(p_orderid =>2397, p_cv_order =>cur_orders);
LOOP
FETCH cur_orders INTO v_ordertab;
EXIT WHEN cur_orders%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('ORDER_ID: ' || v_ordertab.ORDER_ID || ' ORDER_DATE: ' || v_ordertab.ORDER_DATE || ' ORDER_MODE: ' || v_ordertab.ORDER_MODE || ' CUSTOMER_ID: ' || v_ordertab.CUSTOMER_ID);
END LOOP;
exception
when others then
DBMS_OUTPUT.put_line ('Error Code : ' || SQLCODE);
end;
/
Since you're executing this from SQL Developer, you can use the variable and print commands, which are carried over from SQL*Plus:
variable cur_orders refcursor;
exec show_details.get_order(p_orderid => 2397, p_cv_order => :cur_orders);
print cur_orders
CUR_ORDERS
-------------------------------------------------------------------------------------------------------------------------------------------------
ORDER_ID CUSTOMER_ID ORDER_MODE ORDER_DATE
--------------------------------------- --------------------------------------- --------------------------------------- -------------------------
2397 42 0 03-JAN-15
Notice that you're passing the ref cursor variable as a bind variable, so there is a colon before the name in the call (:cur_order). And you need to run script rather than run statement.
exec is just a shorthand for an anonymous block, so you could do it explicitly if you prefer, but the effect is the same:
var cur_orders refcursor;
begin
show_details.get_order(p_orderid => 2397, p_cv_order => :cur_orders);
end;
/
print cur_orders
You can also get the output in the result grid if you prefer, as shown here, but print is a bit closer to your dbms_output version. Or you can have a wrapper function so you could call query the procedure from a plain SQL call; depends what your end goal is, and if you're just manually executing the procedure to check the output then print may also be good enough.

Oracle trigger checks previous record before insert/update

I would like to create a trigger that prevents a student from enrolling into a new module if he has any outstanding bills.
studID studNRIC paymentStatus
-------------------------------------
200 F7654672F Non Payment
it would reject the following statement:
INSERT INTO student(studID, studNRIC, paymentStatus)
VALUES (201, 'F7654672F', 'Good');
I've came out with the following trigger but I'm still able to insert a new student.
set define off;
CREATE OR REPLACE TRIGGER reject_new_account
AFTER INSERT OR UPDATE ON Student
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
totover NUMBER(3);
BEGIN
SELECT COUNT (*)
INTO totover
FROM Student
WHERE :NEW.nric = student.nric
AND :NEW.paymentStatus = 'Non Payment';
IF totover > 0 THEN
RAISE_APPLICATION_ERROR ( -20002,
'Student' || :NEW.nric ||
' has outstanding bills' );
END IF;
END;
/
there's seems to be a problem with line 13 AND :NEW.paymentStatus = 'Non Payment';
so how do I go about doing this?
table structure
CREATE TABLE Student(
studID INTEGER NOT NULL,
firstName CHAR(25) NULL,
lastName CHAR(25) NULL,
NRIC CHAR(9) NOT NULL,
paymentStatus CHAR(25) Default 'Good',
CONSTRAINT stud_Pkey PRIMARY KEY (studID),
CONSTRAINT studPaymentStatus_type CHECK (PaymentStatus IN ('Late Payment', 'Non Payment', 'Good'))
);
There are a couple of issues with this trigger.
First if you want to prevent an INSERT you need to use a BEFORE trigger. An AFTER trigger will fire after the insert has successfully completed, by which point it is too late to stop the insert.
Secondly, I'm unsure about what you are trying to achieve with your SQL statement. Since the trigger is attached to the customer table you don't need to do a select on the customer table to access the record data. You can just do:
IF :NEW.badstatus = 'Non Payment'
THEN
RAISE_APPLICATION_ERROR ( -20002,
'Employee ' || :NEW.nric ||
' already has 5 readings' );
END IF;
You probably don't want to check if the new record has a bad status, you want to check if the existing customer records have a bad status. As James mentioned, a BEFORE trigger probably makes more sense, but that depends on what you are trying to do, whether the insert gets rollback or not by the caller, etc.
CREATE OR REPLACE TRIGGER reject_new_account
AFTER INSERT OR UPDATE ON Customer
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
totover NUMBER(3);
BEGIN
SELECT COUNT (*)
INTO totover
FROM Customer c
WHERE c.nric = :NEW.nric
AND c.badstatus = 'Non Payment';
IF totover > 0 THEN
RAISE_APPLICATION_ERROR ( -20002,
'Employee ' || :NEW.nric ||
' already has 5 readings' );
END IF;
END;
/
I've removed the PRAGMA AUTONOMOUS_TRANSACTION; for you and replace it with an exception to handle the issue, can you try if it works.
set define off;
CREATE OR REPLACE TRIGGER reject_new_account
BEFORE INSERT OR UPDATE ON CUSTOMER
FOR EACH ROW
DECLARE
totover CHAR(100);
BEGIN
SELECT distinct badStatus
INTO totover
FROM customer
WHERE :NEW.nric = CUSTOMER.nric;
IF totover = 'Non Payment' THEN
RAISE_APPLICATION_ERROR ( -20003,
'Customer ' || :NEW.firstName||''||:NEW.lastName ||
' cannot create new account due to bad payment' );
END IF;
EXCEPTION
WHEN NO_DATA_FOUND
THEN DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQLERRM(-20299)));
END;
/
As I assume you have discovered, you cannot select from the same table that a row-level trigger is defined against; it causes a table mutating exception. You have attempted to get round this by adding the autonomous transaction pragma. Unfortunately, although this works, it is just covering up your mistake in methodology.
In order to properly create this validation using a trigger a procedure should be created to obtain user-specified locks so the validation can be correctly serialized in a multi-user environment.
PROCEDURE request_lock
(p_lockname IN VARCHAR2
,p_lockmode IN INTEGER DEFAULT dbms_lock.x_mode
,p_timeout IN INTEGER DEFAULT 60
,p_release_on_commit IN BOOLEAN DEFAULT TRUE
,p_expiration_secs IN INTEGER DEFAULT 600)
IS
-- dbms_lock.allocate_unique issues implicit commit, so place in its own
-- transaction so it does not affect the caller
PRAGMA AUTONOMOUS_TRANSACTION;
l_lockhandle VARCHAR2(128);
l_return NUMBER;
BEGIN
dbms_lock.allocate_unique
(lockname => p_lockname
,lockhandle => p_lockhandle
,expiration_secs => p_expiration_secs);
l_return := dbms_lock.request
(lockhandle => l_lockhandle
,lockmode => p_lockmode
,timeout => p_timeout
,release_on_commit => p_release_on_commit);
IF (l_return = 1) THEN
raise_application_error(-20001, 'dbms_lock.request Timeout');
ELSIF (l_return = 2) THEN
raise_application_error(-20001, 'dbms_lock.request Deadlock');
ELSIF (l_return = 3) THEN
raise_application_error(-20001, 'dbms_lock.request Parameter Error');
ELSIF (l_return = 5) THEN
raise_application_error(-20001, 'dbms_lock.request Illegal Lock Handle');
ELSIF (l_return not in (0,4)) THEN
raise_application_error(-20001, 'dbms_lock.request Unknown Return Value ' || l_return);
END IF;
-- Must COMMIT an autonomous transaction
COMMIT;
END request_lock;
This procedure can then be used in a compound trigger (assuming at least Oracle 11, this will need to be split into individual triggers in earlier versions)
CREATE OR REPLACE TRIGGER reject_new_account
FOR INSERT OR UPDATE ON student
COMPOUND TRIGGER
-- Table to hold identifiers of inserted/updated students
g_studIDs sys.odcinumberlist;
BEFORE STATEMENT
IS
BEGIN
-- Reset the internal student table
g_studIDs := g_studIDs();
END BEFORE STATEMENT;
AFTER EACH ROW
IS
BEGIN
-- Store the inserted/updated students; the payment status may be updated
-- without checking the constraint
IF ( INSERTING
OR ( UPDATING
AND ( :new.studID <> :old.studID
OR :new.NRIC <> :old.NRIC)))
THEN
g_studIDs.EXTEND;
g_studIDs(g_studIDs.LAST) := :new.studID;
END IF;
END AFTER EACH ROW;
AFTER STATEMENT
IS
CURSOR csr_students
IS
SELECT sdt.studID
, sdt.NRIC
FROM TABLE(g_studIDs) sid
INNER JOIN student sdt
ON (sdt.studID = sid.column_value)
ORDER BY sdt.NRIC;
CURSOR csr_constraint_violations
(p_studID student.studID%TYPE
,p_NRIC student.studNRIC%TYPE)
IS
SELECT NULL
FROM student sdt
WHERE sdt.NRIC = p_NRIC
AND sdt.paymentStatus = 'Bad Payment'
AND sdt.studID <> p_studID;
r_constraint_violation csr_constraint_violations%ROWTYPE;
BEGIN
-- Check if for any inserted/updated student there exists another record for
-- the same NRIC with a Bad Payment status. Serialise the constraint for each
-- NRIC so concurrent transactions do not affect each other
FOR r_student IN csr_students LOOP
request_lock('REJECT_NEW_ACCOUNT_' || r_student.NRIC);
OPEN csr_constraint_violations(r_student.studID, r_student.NRIC);
FETCH csr_constraint_violations INTO r_constraint_violation;
IF csr_constraint_violations%FOUND THEN
CLOSE csr_constraint_violations;
raise_application_error(-20001, 'Student ' || r_student.NRIC || ' has Bad Payment status');
ELSE
CLOSE csr_constraint_violations;
END IF;
END LOOP;
END AFTER STATEMENT;
END;

Resources