i have code on oracle apex need to loop on a collection and then if the primary key is dublicated
then i must update if others then insert new one.
this is my code but give me errors.
BEGIN
FOR r1
IN (SELECT *
FROM apex_application_temp_files f,
TABLE (
apex_data_parser.parse (
p_content => f.blob_content,
p_add_headers_row => 'Y',
p_file_name => f.filename)) p
WHERE f.name = :p24_upload AND line_number > 1)
LOOP
apex_collection.add_member (
p_collection_name => 'W',
p_c001 => NVL (REPLACE (r1.col001, '-', ''), NULL),
p_c002 => NVL (REPLACE (r1.col002, '-', ''), NULL),
p_c003 => NVL (REPLACE (r1.col003, '-', ''), NULL),
p_c004 => NVL (REPLACE (r1.col004, '-', ''), NULL),
p_c005 => NVL (REPLACE (r1.col005, '-', ''), NULL),
p_c006 => NVL (REPLACE (r1.col006, '-', ''), NULL),
p_c007 => NVL (REPLACE (r1.col007, '-', ''), NULL),
p_c008 => NVL (REPLACE (r1.col008, '-', ''), NULL),
p_c009 => NVL (REPLACE (r1.col009, '-', ''), NULL),
p_c010 => NVL (REPLACE (r1.col010, '-', ''), NULL),
p_c011 => NVL (REPLACE (r1.col011, '-', ''), NULL),
p_c012 => NVL (REPLACE (r1.col012, '-', ''), NULL),
p_c013 => NVL (REPLACE (r1.col013, '-', ''), NULL),
p_c014 => NVL (REPLACE (r1.col014, '-', ''), NULL),
p_c015 => NVL (REPLACE (r1.col015, '-', ''), NULL),
p_c016 => NVL (REPLACE (r1.col016, '-', ''), NULL),
p_c017 => NVL (REPLACE (r1.col017, '-', ''), NULL),
p_c018 => NVL (REPLACE (r1.col018, '-', ''), NULL),
p_c019 => NVL (REPLACE (r1.col019, '-', ''), NULL),
p_c020 => NVL (REPLACE (r1.col020, '-', ''), NULL),
p_c021 => NVL (REPLACE (r1.col021, '-', ''), NULL),
p_c022 => NVL (REPLACE (r1.col022, '-', ''), NULL),
p_c023 => NVL (REPLACE (r1.col023, '-', ''), NULL),
p_c024 => NVL (REPLACE (r1.col024, '-', ''), NULL),
p_c025 => NVL (REPLACE (r1.col025, '-', ''), NULL));
END LOOP;
END; 1
DECLARE
CURSOR c2
IS
(SELECT *
FROM apex_collections
WHERE collection_name = 'W');
BEGIN
FOR i IN c2
LOOP
MERGE INTO pos_cards_new NEWS
USING (SELECT *
FROM apex_collections
WHERE collection_name = 'W') STC
ON( NEWS.card_seq = I.C001 )
WHEN MATCHED THEN
UPDATE pos_cards_new
SET card_amt = I.C005,
iuser_id = :app_user,
itime_stamp = SYSDATE,
valid_from_date = I.C007,
vald_to_date = I.C008
WHERE card_seq = I.C001;
WHEN NOT MATCHED THEN
INSERT INTO pos_cards_new (comp_id,
card_seq,
curncy_code,
curr_rate,
card_amt,
card_base_amt,
valid_from_date,
vald_to_date,
card_points,
card_balance,
card_isvalid,
iuser_id,
itime_stamp,
card_id,
customer_code,
employee_cridet_limit,
employee_cridet_curr_balance,
is_admin)
VALUES (
'IPOS',
I.C001,
(SELECT curncy_code
FROM pos_stp_currencies
WHERE curncy_desc_m = i.c003
AND comp_id = :p0_comp_id),
I.C004,
I.C005,
I.C006,
TO_CHAR (TO_DATE (I.C007, 'YYYYMMDD'),'dd/mm/yyyy'),
TO_CHAR (TO_DATE (I.C008, 'YYYYMMDD'),'dd/mm/yyyy'),
I.C009,
I.C010,
I.C014,
:app_user,
SYSDATE,
I.C002,
I.C013,
I.C015,
I.C016,
I.C017);
END LOOP; -------------------3
END;
---- the primary key is card_seq with in collection is I.C001
EXPECTED TO CORRECT MY CODE
Related
We are currently prototyping a REST API using the Oracle APEX cloud free tier. I’m having an issue with returning a sys_refcursor in an Oracle REST POST request. Here’s the particulars (I'm new at asking questions here so I hope the formatting is readable:
TABLE
CREATE TABLE "WF_PROTOTYPE"."INGREDIENT_TYPES"
( "ID" NUMBER(10,0) NOT NULL ENABLE,
"ACCOUNT_ID" NUMBER(10,0) NOT NULL ENABLE,
"NAME" VARCHAR2(100 CHAR) COLLATE "USING_NLS_COMP" NOT NULL ENABLE,
"CREATED_AT" TIMESTAMP (6), "UPDATED_AT" TIMESTAMP (6),
"DELETED_AT" TIMESTAMP (6), "CREATED_BY" NUMBER(10,0),
"UPDATED_BY" NUMBER(10,0), "DELETED_BY" NUMBER(10,0),
"DESCRIPTION" VARCHAR2(1000 BYTE) COLLATE "USING_NLS_COMP",
CONSTRAINT "INGR_TYPE_PK" PRIMARY KEY ("ID"))
TRIGGER
create or replace TRIGGER ingredient_types_id_TRIG BEFORE INSERT OR UPDATE ON ingredient_types
FOR EACH ROW
DECLARE
v_newVal NUMBER(12) := 0;
v_incval NUMBER(12) := 0;
BEGIN
IF INSERTING AND :new.id IS NULL THEN
SELECT ingredient_types_id_SEQ.NEXTVAL INTO v_newVal FROM DUAL;
-- If this is the first time this table have been inserted into (sequence == 1)
IF v_newVal = 1 THEN
--get the max indentity value from the table
SELECT NVL(max(id),0) INTO v_newVal FROM ingredient_types;
v_newVal := v_newVal + 1;
--set the sequence to that value
LOOP
EXIT WHEN v_incval>=v_newVal;
SELECT ingredient_types_id_SEQ.nextval INTO v_incval FROM dual;
END LOOP;
END IF;
-- assign the value from the sequence to emulate the identity column
:new.id := v_newVal;
END IF;
END;
STORED PROCEDURE
create or replace PROCEDURE ingredient_type_POST (
p_account_id IN ingredient_types.account_id%TYPE,
p_name IN ingredient_types.name%TYPE,
p_description in ingredient_types.description%type,
p_created_by IN ingredient_types.created_by%type,
p_out_rec OUT sys_refcursor
)
AS
new_id ingredient_types.id%type;
BEGIN
INSERT INTO ingredient_types (account_id, name, DESCRIPTION, created_at, created_by)
VALUES (p_account_id, p_name, p_description, systimestamp, nvl(p_created_by,2))
RETURN id INTO new_id;
OPEN p_out_rec FOR
SELECT id, account_id, name, description
FROM ingredient_types
WHERE ID = new_id;
EXCEPTION
WHEN OTHERS
THEN HTP.print(SQLERRM);
END ingredient_type_POST;
ORDS DEFINITION
ORDS.DEFINE_HANDLER(
p_module_name => 'wf_api.rest',
p_pattern => 'accounts/:acct_id/ingredient_types',
p_method => 'POST',
p_source_type => 'plsql/block',
p_items_per_page => 0,
p_mimes_allowed => '',
p_comments => 'CREATE an Ingredient Type',
p_source =>
'begin
INGREDIENT_TYPE_POST(
p_account_id => :acct_id,
p_name => :name,
p_description => :description,
p_created_by => :APP_USER,
p_rec => :new_rec);
end;'
);
ORDS.DEFINE_PARAMETER(
p_module_name => 'wf_api.rest',
p_pattern => 'accounts/:acct_id/ingredient_types',
p_method => 'POST',
p_name => 'rec',
p_bind_variable_name => 'new_rec',
p_source_type => 'RESPONSE',
p_param_type => 'RESULTSET',
p_access_method => 'OUT',
p_comments => NULL);
When I run the SP from the SQL Developer worksheet EDITOR, filling in the input variables I get a successful result (New record created) and it returns the anticipated resultset in the p_out_rec parameter. However, when I run it in the HANDLER editor, filling out the appropriate variables, I get the following error message:
Error starting at line : 1 in command -
begin
INGREDIENT_TYPE_POST(
p_account_id => :acct_id,
p_name => :name,
p_description => :description,
p_created_by => :APP_USER,
p_rec => :new_rec);
end;
Error report -
ORA-06550: line 2, column 5:
PLS-00306: wrong number or types of arguments in call to 'INGREDIENT_TYPE_POST'
ORA-06550: line 2, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I’ve tried to mimic ThatJeffSmith’s tutorial https://www.thatjeffsmith.com/archive/2017/03/parameters-and-binds-for-your-restful-services-resultsets/ as closely as possible, and I’m not seeing where my fault lies… any insights greatly appreciated!!!
Found a couple of issues with your code.
you're not supplying a value for the table's ID column
your refcursor is being populated with a query that will mostly never
work, you're checking the ID against the ACCOUNT_ID value
you're referring to p_out_rec as p_rec -- thanks #andrew!
Here's how it could work
-- Generated by ORDS REST Data Services 20.4.1.r0131644
-- Schema: HR Date: Wed Mar 17 05:24:17 2021
--
BEGIN
ORDS.ENABLE_SCHEMA(
p_enabled => TRUE,
p_schema => 'HR',
p_url_mapping_type => 'BASE_PATH',
p_url_mapping_pattern => 'hr',
p_auto_rest_auth => FALSE);
ORDS.DEFINE_MODULE(
p_module_name => 'wf_api.rest',
p_base_path => '/wf_api/',
p_items_per_page => 25,
p_status => 'PUBLISHED',
p_comments => 'stackoverflow question');
ORDS.DEFINE_TEMPLATE(
p_module_name => 'wf_api.rest',
p_pattern => 'accounts/:acct_id/ingredient_types',
p_priority => 0,
p_etag_type => 'HASH',
p_etag_query => NULL,
p_comments => NULL);
ORDS.DEFINE_HANDLER(
p_module_name => 'wf_api.rest',
p_pattern => 'accounts/:acct_id/ingredient_types',
p_method => 'POST',
p_source_type => 'plsql/block',
p_mimes_allowed => '',
p_comments => NULL,
p_source =>
'begin
INGREDIENT_TYPE_POST(
P_ID => :id,
P_ACCOUNT_ID => :acct_id,
P_NAME => :name,
P_DESCRIPTION => :description,
P_CREATED_BY => :APP_USER,
P_OUT_REC => :new_rec
);
END;');
ORDS.DEFINE_PARAMETER(
p_module_name => 'wf_api.rest',
p_pattern => 'accounts/:acct_id/ingredient_types',
p_method => 'POST',
p_name => 'rec',
p_bind_variable_name => 'new_rec',
p_source_type => 'RESPONSE',
p_param_type => 'RESULTSET',
p_access_method => 'OUT',
p_comments => NULL);
COMMIT;
END;
And the PL/SQL proc...
create or replace PROCEDURE ingredient_type_POST (
p_id IN ingredient_types.id%TYPE,
p_account_id IN ingredient_types.account_id%TYPE,
p_name IN ingredient_types.name%TYPE,
p_description in ingredient_types.description%type,
p_created_by IN ingredient_types.created_by%type,
p_out_rec OUT sys_refcursor
)
AS
new_id ingredient_types.id%type;
BEGIN
INSERT INTO ingredient_types (id, account_id, name, DESCRIPTION, created_at, created_by)
VALUES (p_id, p_account_id, p_name, p_description, systimestamp, nvl(p_created_by,2))
RETURN id INTO new_id;
OPEN p_out_rec FOR
SELECT id, account_id, name, description
FROM ingredient_types
WHERE account_ID = p_account_id;
EXCEPTION
WHEN OTHERS
THEN HTP.print(SQLERRM);
END ingredient_type_POST;
And the request -
curl --request POST \
--url http://localhost:8080/ords/hr/wf_api/accounts/42/ingredient_types \
--header 'Content-Type: application/json' \
--data '{
"id". : 55,
"name" : "heyYou",
"description" : "some words",
"APP_USER" : 44
}'
I need to create schedule for run jobs in oracle. It'll run at first workday of month, but excluding holidays. When first workday of month is holiday, than run should be next workday after holiday.
I managed with first workday of each month and exclude holidays, but I don't know how to set run on workday after holiday...
HOLIDAYS
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => 'SCHDL_COM_HOLIDAYS',
repeat_interval => 'FREQ=YEARLY; BYDATE=0101,0111;'
);
FIRST WORKDAY
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => 'SCHDL_FIRST_WD',
repeat_interval => 'FREQ=MONTHLY; BYDAY=MON,TUE,WED,THU,FRI; EXCLUDE=SCHDL_COM_HOLIDAYS; BYSETPOS=1'
);
Please follow the below steps:
1) Create schedule for all the holidays.
BEGIN
DBMS_SCHEDULER.create_schedule (
schedule_name => 'NYD_FRI',
repeat_interval => 'FREQ=YEARLY;BYDATE=1231;BYDAY=FRI',
comments => 'Friday alternative for New Year''s Day');
DBMS_SCHEDULER.create_schedule (
schedule_name => 'NYD_MON',
repeat_interval => 'FREQ=YEARLY;BYDATE=0102;BYDAY=MON',
comments => 'Monday alternative for New Year''s Day');
DBMS_SCHEDULER.create_schedule (
schedule_name => 'NewYearsDay',
repeat_interval => 'FREQ=YEARLY;BYDATE=0101;BYDAY=MON,TUE,WED,THU,FRI;'
|| 'INCLUDE=NYD_FRI,NYD_MON',
comments => 'New Year''s Day');
);
END;
/
2) Create a schedule which clubs all the schedule created above.
BEGIN
DBMS_SCHEDULER.create_schedule (
schedule_name => 'FederalHolidays',
repeat_interval => 'NewYearsDay,MartinLutherKing,PresidentsDay,',
comments => 'Federal Holidays');
END;
3) Create a job, note the “EXCLUDE” and “BYSETPOS” option
BEGIN
DBMS_SCHEDULER.create_job (
job_name => 'Run_Next_Day',
job_type => 'PLSQL_BLOCK',
job_action => 'begin Run_Next_Day; end; ',
repeat_interval => 'FREQ=MONTHLY; BYDAY=MON,TUE,WED,THU,FRI; byhour=14;byminute=30;bysecond=0; EXCLUDE=FederalHolidays; BYSETPOS=7',
enabled => TRUE,
comments => 'Skipping Holidays');
END;
/
#XING thank You for Your help. I modified your solution exactly to my needs.
The answer exactly for my problem is
New Year's Day
BEGIN
DBMS_SCHEDULER.create_schedule (
schedule_name => 'SCHD_NYD_MON',
repeat_interval => 'FREQ=YEARLY;BYDATE=0101;BYDAY=MON',
comments => 'Monday alternative for New Year''s Day');
DBMS_SCHEDULER.create_schedule (
schedule_name => 'SCHD_NEW_YEAR_DAY',
repeat_interval => 'FREQ=YEARLY;BYDATE=0101;BYDAY=MON,TUE,WED,THU,FRI;'
|| 'INCLUDE=SCHD_NYD_MON',
comments => 'New Year''s Day');
END;
/
First November's Day
BEGIN
DBMS_SCHEDULER.create_schedule (
schedule_name => 'SCHD_FNOV_MON',
repeat_interval => 'FREQ=YEARLY;BYDATE=1101;BYDAY=MON',
comments => 'Monday alternative for First November');
DBMS_SCHEDULER.create_schedule (
schedule_name => 'SCHD_FIRST_NOVEMBER',
repeat_interval => 'FREQ=YEARLY;BYDATE=1101;BYDAY=MON,TUE,WED,THU,FRI;'
|| 'INCLUDE=SCHD_FNOV_MON',
comments => 'First November''s Day');
END;
/
Federal Holidays
BEGIN
DBMS_SCHEDULER.create_schedule (
schedule_name => 'SCHD_HOLIDAYS',
repeat_interval => 'SCHD_NEW_YEAR_DAY,SCHD_FIRST_NOVEMBER',
comments => 'Federal Holidays');
END;
/
Job
BEGIN
DBMS_SCHEDULER.create_job (
job_name => 'Run_Next_Day',
job_type => 'PLSQL_BLOCK',
job_action => 'begin Run_Next_Day; end; ',
repeat_interval => 'FREQ=MONTHLY; BYDAY=MON,TUE,WED,THU,FRI;
byhour=12;byminute=0;bysecond=0;
EXCLUDE=SCHD_HOLIDAYS; BYSETPOS=1',
enabled => TRUE,
comments => 'Skipping Holidays');
END;
/
When i excute a merge statement:
merge into employees e using new_employees n
on (e.employee_id = n.employee_id)
when matched then
update set e.salary = n.salary
when not matched then
insert (employee_id,first_name,last_name,email,phone_number,hire_date,
job_id,salary,commission_pct,manager_id,department_id)
values (n.employee_id,n.first_name,n.last_name,n.email,n.phone_number,
n.hire_date,n.job_id,n.salary,n.commission_pct,n.manager_id,
n.department_id);
it reports:ORA-28138:An invalid policy predicate was specified.
What's wrong with me?
I find this error is caused by Fine_Grained Auditing.I had created a policy before as below:
DBMS_FGA.add_policy (object_schema => 'primer',
object_name => 'employees',
policy_name => 'audit_policy',
audit_condition => 'employee_id = 100',
audit_column => 'phone_number,salary',
handler_schema => 'primer',
handler_module => 'FGA_SEND_MAIL(primer,employees,audit_policy)',
ENABLE => TRUE,
statement_types => 'select,insert,update,delete',
audit_trail => DBMS_FGA.db_extended,
audit_column_opts => DBMS_FGA.any_columns);
create or replace procedure primer.fga_send_mail (p_schema in varchar2,
p_obj in varchar2,
p_pol in varchar2)
as
begin
dbms_output.put_line ('Audit Trail Generated');
dbms_output.put_line ('SQL=' || sys_context ('USERENV', 'CURRENT_SQL'));
dbms_output.put_line ('USER' || sys_context ('USERENV', 'SESSION_USER'));
end;
What wrong with it?
I'm trying to create an Oracle Job for c_insert_ship_confirm_start.
BEGIN
SYS.DBMS_SCHEDULER.CREATE_JOB (
job_name => '"CRCTFDC11XRQA"."SHIP_CONFIRM_JOB"',
job_type => 'STORED_PROCEDURE',
job_action => 'c_insert_ship_confirm_start(1000,FDC,1,0)',
number_of_arguments => 0,
start_date => TO_TIMESTAMP('09-MAR-16 02.41.43.451000000 PM', 'DD-MON-RR HH.MI.SS.FF AM'),
repeat_interval => 'FREQ=DAILY;BYDAY=FRI,MON,SAT,SUN,THU,TUE,WED;BYMINUTE=5',
end_date => NULL,
job_class => 'DEFAULT_JOB_CLASS',
enabled => false,
auto_drop => true,
comments => 'SHIP_CONFIRM_JOB IN EVERY 5 MINS',
credential_name => NULL,
destination_name => NULL);
END;
Stored procedure for reference::
create or replace procedure c_insert_ship_confirm_start
(
p_commit_frequency in number default 1000,
p_whse in varchar2,
p_debug_flag in number default 0,
p_rc out number
)
while creating JOB Oracle throwing error::
ORA-27452: %s is an invalid name for a database object
Arguments are not supported with stored_procedure job type. Reference: Oracle Docs
Use plsql_block
BEGIN
sys.dbms_scheduler.create_job(job_name => '"CRCTFDC11XRQA"."SHIP_CONFIRM_JOB"',
job_type => 'PLSQL_BLOCK',
job_action => 'begin c_insert_ship_confirm_start(1000,''FDC'',1,0); end;',
number_of_arguments => 0,
start_date => to_timestamp('09-MAR-16 02.41.43.451000000 PM',
'DD-MON-RR HH.MI.SS.FF AM'),
repeat_interval => 'FREQ=DAILY;BYDAY=FRI,MON,SAT,SUN,THU,TUE,WED;BYMINUTE=5',
end_date => NULL,
job_class => 'DEFAULT_JOB_CLASS',
enabled => FALSE,
auto_drop => TRUE,
comments => 'SHIP_CONFIRM_JOB IN EVERY 5 MINS',
credential_name => NULL,
destination_name => NULL);
END;
/
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
JOB_NAME => 'BillsDueCheck',
JOB_TYPE => 'PLSQL_BLOCK',
JOB_ACTION => 'BEGIN
UPDATE Customer C
SET C.Standing = 'B'
WHERE C.CustomerID IN (
SELECT B.CUSTOMERID
FROM Bill B
WHERE (BillDate + 60) < SYSDATE);
END;',
START_DATE => SYSTIMESTAMP,
REPEAT_INTERVAL => 'FREQ=DAILY'
END_DATE => NULL,
ENABLED => TRUE,
COMMENTS => 'Checks if the bill is overdue'
);
END;
The error occurs at the SET line I think I must be doing something wrong further up but I'm not sure.
I have tried running the job action by it's self and it works fine.
You must double your quotes around your 'B' otherwise oracle will think your string is terminated and try to interpret the B as a command.
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
JOB_NAME => 'BillsDueCheck',
JOB_TYPE => 'PLSQL_BLOCK',
JOB_ACTION => 'BEGIN
UPDATE Customer C
SET C.Standing = ''B''
WHERE C.CustomerID IN (
SELECT B.CUSTOMERID
FROM Bill B
WHERE (BillDate + 60) < SYSDATE);
END;',
START_DATE => SYSTIMESTAMP,
REPEAT_INTERVAL => 'FREQ=DAILY'
END_DATE => NULL,
ENABLED => TRUE,
COMMENTS => 'Checks if the bill is overdue'
);
END;