Create email notification request link function - oracle

I created a function to create link but am encountering errors when creating a variable, tried declaring but declare would have an error
create or replace FUNCTION CREATE_REQUEST_LINK(request_id IN VARCHAR2, task_id IN VARCHAR2)
RETURN VARCHAR2 AS
request_link varchar2(100);
BEGIN
first_half varchar2 := apex_mail.get_instance_url;
second_half varchar2 := 'f?p=&APP_ID.:&APP_PAGE.:&APP_SESSION.::::';
request_link := first_half + second_half;
RETURN request_link;
END WF_CREATE_REQUEST_LINK;
It was returning on Line 8 and 9
Error: PLS-00103: Encountered the symbol "VARCHAR2" when expecting one of the following: := . ( # % ; The symbol "." was substituted for "VARCHAR2" to continue.
Is there a way to fix. I'm kinda new to Oracle Apex
Additional question, am I right in creating the 2nd half, the plan is that the $APP_SESSION. after clicking the link will be changed into the session id after logging in.

You seem to want to declare two local variables first_half and second_half. Variable declarations need to happen in the declaration section of a block.
When you declare a varchar2 variable, you need to provide a length. I'll guess that you want both local variables to have a maximum length of 100.
The string concatenation operator is || not +
So you probably want something like
create or replace FUNCTION CREATE_REQUEST_LINK(
request_id IN VARCHAR2,
task_id IN VARCHAR2)
RETURN VARCHAR2
AS
request_link varchar2(100);
first_half varchar2(100) := apex_mail.get_instance_url;
second_half varchar2(100) := 'f?p=&APP_ID.:&APP_PAGE.:&APP_SESSION.::::';
BEGIN
request_link := first_half || second_half;
RETURN request_link;
END WF_CREATE_REQUEST_LINK;

Related

writing function but been getting this error

the question:
Write a blocK PL/SQL that display the total commission amount of a job id. Use function “compute_commission” that accepts a job id equal to 9 and return his total commission of all corresponding employees.
the error:
`Error at line 11: PLS-00103: Encountered the symbol "DECLARE"
CREATE OR REPLACE FUNCTION compute_commission (C_employee_id in number)
RETURN number
is `
the code:
CREATE OR REPLACE FUNCTION compute_commission (C_employee_id in number)
RETURN number
is
sum_commission number;
begin
select sum(job_id)
into sum_commission from employees
where employee_ref_id = C_employee_id;
return sum_commission;
end compute_commission;
declare
cal_sum_commission number;
begin
cal_sum_commission = compute_commission(cal_sum_commission);
dbms_output.put_line ('employee commission is: ' || compute_commission(cal_sum_commission);
end;
Should be something like this:
CREATE OR REPLACE FUNCTION compute_commission (C_employee_id IN NUMBER)
RETURN NUMBER
IS
sum_commission NUMBER;
BEGIN
SELECT SUM (job_id)
INTO sum_commission
FROM employees
WHERE employee_ref_id = C_employee_id;
RETURN sum_commission;
END compute_commission;
/
DECLARE
cal_sum_commission NUMBER := 12345;
BEGIN
cal_sum_commission := compute_commission (cal_sum_commission);
DBMS_OUTPUT.put_line (
'employee commission is: ' || cal_sum_commission);
END;
/
Note that I modified anonymous PL/SQL block and
added local variable's value (otherwise you'd pass NULL to the function) (you'll, of course, use some valid value; this - 12345 - is just an example)
used local variable in DBMS_OUTPUT.PUT_LINE
terminated statement with a semi-colon (you've had a colon)
fixed assignment operator (:= instead of just =)
Also, is sum_commision really sum of JOB_ID values? Looks strange to me ...

What do these errors mean and how do you suggest I fix them?

I am new to learning SQL and currently learning it in class. I am trying to write a code that fulfills the following requirements:
Make a reservation: Input parameters: Hotel, guest’s name, start date, end dates, room type, date of reservation. Output: reservation ID. NOTE: Only one guest per reservation. However, the same guest can make multiple reservations.
Find a reservation: Input is the guest’s name and date, hotel ID. The output is reservation ID
I am still somewhat new to deciphering error codes and tried to look up what they mean. However, I'm still not quite sure why my code is wrong.
CREATE OR REPLACE PACKAGE hotelmanagement AS
FUNCTION make(rsrv_id VARCHAR2
,hotel_name VARCHAR2
,guest VARCHAR2
,start_date VARCHAR2
,end_date VARCHAR2
,room_type VARCHAR2
,rsrv_date VARCHAR2)
RETURN NUMBER IS
rsrv_id NUMBER;
BEGIN
SELECT rsrv_seq.nextval INTO reserve_id FROM dual;
INSERT INTO reservations
VALUES
(reserve_id, 'Four Seasons', 'Amanda', 'July-30-2019', 'Aug-8-2019',
'King', 'July-18-2019');
tot_rsrv := tot_rsrv + 1;
RETURN(rsrv_id);
END;
FUNCTION find(guest VARCHAR2
,rsrv_date VARCHAR2)
RETURN NUMBER IS
rsrv_id NUMBER;
BEGIN
SELECT rsrv_id
INTO guest
FROM reservations
WHERE rsrv_date = find_rsrv_date;
END;
RETURN(rsrv_id);
END hotelmanagement;
I have these error messages(two of them look the same?):
Error(4,1): PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: begin function pragma procedure subtype type current cursor delete exists prior The symbol "begin" was substituted for "SELECT" to continue.
Error(5,1): PLS-00103: Encountered the symbol "RSRV_ID" when expecting one of the following: language
Error(5,1): PLS-00103: Encountered the symbol "RSRV_ID" when expecting one of the following: language
The requirements are a quite vague, so it is difficult to provide the desired procedure. Anyway, your code has some weak items.
Your procedure has several input parameters but you don't use them inside the procedure.
Use appropriate data types, i.e. never(!) store DATE or number values in string, i.e. VARCHAR2. Use VARCHAR2 only for string data. At least you use four digit year, which is the proper way of doing it.
RETURN command does not use brackets.
Taking all this into account your code should be more or less like this:
CREATE OR REPLACE PACKAGE BODY hotelmanagement AS
FUNCTION make( -- you can't declare variable "rsrv_id" twice
hotel_name IN VARCHAR2
,guest IN VARCHAR2
,start_date IN DATE
,end_date IN DATE
,room_type IN VARCHAR2
,rsrv_date IN DATE)
RETURN NUMBER IS
rsrv_id NUMBER;
BEGIN
INSERT INTO reservations
VALUES
(rsrv_seq.nextval, hotel_name, guest, start_date, end_date,
room_type, rsrv_date)
RETURNING reserve_id INTO rsrv_id ;
-- tot_rsrv := tot_rsrv + 1; -> I don't see any use for it, variable tot_rsrv is not declared
RETURN rsrv_id;
END;
FUNCTION find(v_guest IN VARCHAR2
,rsrv_date IN DATE) RETURN NUMBER IS
rsrv_id NUMBER;
BEGIN
SELECT rsrv_id
INTO rsrv_id
FROM reservations
WHERE rsrv_date = find_rsrv_date
and guest = v_guest; -- don't use "guest = guest" because this will select all rows.
RETURN rsrv_id;
END;
END hotelmanagement;

How to pass record type value to function argument

May I know how to pass a record type value to a function argument?
Below is my attempt. I'm getting "wrong number or types of arguments in call..." error
I've searched but couldn't seem to find definite answer that will help me.
Hope someone can answer.
DECLARE
TYPE attribute_type_record IS RECORD
(
name VARCHAR2(100)
,value VARCHAR2(400)
,ind integer
);
type attribute_type is table of attribute_type_record index by binary_integer;
sid_att attribute_type;
ret varchar2(3000);
BEGIN
sid_att(1).name := 'SID_ATTRIBUTES.REFERENCE1';
sid_att(1).value := 'SID_ATTRIBUTES.REFERENCE1';
sid_att(1).ind := '1';
--v_row := sid_attributes_table('SID_ATTRIBUTES.REFERENCE1');
ret := SC$DATA_ENTRY.ins_sid_attributes(sid_att(1).name,
sid_att(1).value,
sid_att(1).ind,
'594191176',
'TEST');
END;
FUNCTION ins_sid_attributes (
p_sid_attributes_table sc$data_entry_utilities.attribute_table,
p_sid_id sid_attributes.sid_id%TYPE,
p_user IN VARCHAR2
)
RETURN VARCHAR2
IS
error_message VARCHAR2 (2000);
v_row sc$data_entry_utilities.attribute_type;
empty_row sc$data_entry_utilities.attribute_type;
v_order INTEGER := 0;
v_name VARCHAR2 (2000);
cat_table pkg_utilities.number_table;
-- I did not post the rest of the code of this function since i believe it is irrelevant to the error and to keep it short.
Thanks in advance!
noth
Assuming that the INS_SID_ATTRIBUTES procedure shown above is the one you're actually trying to call, the message seems reasonable to me. INS_SID_ATTRIBUTES, as shown above, wants three parameters:
A SC$DATA_ENTRY_UTILITIES.ATTRIBUTE_TABLE
A SID_ATTRIBUTES.SID_ID%TYPE
A VARCHAR2
But in the call you're passing it:
A VARCHAR2
A VARCHAR2
An INTEGER
A VARCHAR2
A VARCHAR2
So you're passing five arguments to a procedure that only accepts three, and the values you're passing are of the wrong types.
Share and enjoy.

How to debug a user defined aggregate function in Oracle 11g?

I'm trying to learn how to create a user defined aggregate function. So far, I've been able to create one that compiles fine, but calling it gives an unexpected result. The function is a very simple test function that looks through a number of rows that are either set to 'Y' or 'N' and returns 'Y' if all are set to 'Y' and otherwise returns 'N'. I'm running it on a single row and getting back a blank varchar 2 instead.
I'm not sure what is the procedure to go through with debugging this. I've tried using DBMS_OUTPUT.PUT_LINE(), but I cannot see anything on the database output. The largest problem is that it is creating the function fine, and most of the code is in an object type. Thus, if I were to try to debug the select statement, it is calling code on the database that has already been compiled.
Below is the code for the function, but I don't want to know why this isn't working as much as I want to know how to debug so I can solve these issues myself, especially when more complex aggregate functions are involved.
CREATE OR REPLACE TYPE MYSCHEMA.ALL_TRUE_T AS OBJECT
(
TRUE_SO_FAR VARCHAR2(1),
STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT ALL_TRUE_T) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT ALL_TRUE_T, value IN VARCHAR2) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(self IN ALL_TRUE_T, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT ALL_TRUE_T, ctx2 IN ALL_TRUE_T) RETURN NUMBER
);
CREATE OR REPLACE TYPE BODY MYSCHEMA.ALL_TRUE_T IS
STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT ALL_TRUE_T)
RETURN NUMBER IS
BEGIN
sctx := ALL_TRUE_T('Y');
return ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT ALL_TRUE_T, value IN VARCHAR2)
RETURN NUMBER IS
BEGIN
IF value <> 'Y' OR self.TRUE_SO_FAR <> 'Y' THEN
self.TRUE_SO_FAR := 'N';
END IF;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateTerminate(self IN ALL_TRUE_T, returnValue OUT VARCHAR2, flags IN NUMBER)
RETURN NUMBER IS
BEGIN
returnValue := self.TRUE_SO_FAR;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT ALL_TRUE_T, ctx2 IN ALL_TRUE_T)
RETURN NUMBER IS
BEGIN
IF ctx2.TRUE_SO_FAR = 'N' THEN
self.TRUE_SO_FAR := 'N';
END IF;
RETURN ODCIConst.Success;
END;
END;
CREATE OR REPLACE PACKAGE MYSCHEMA.ALL_TRUE_PKG IS
FUNCTION ALL_TRUE (input VARCHAR2) RETURN VARCHAR2;
END;
CREATE OR REPLACE PACKAGE BODY MYSCHEMA.ALL_TRUE_PKG IS
FUNCTION ALL_TRUE (input VARCHAR2) RETURN VARCHAR2
AGGREGATE USING ALL_TRUE_T;
END;
And here is how I call it. YN_TEST_TABLE currently has a single row with an 'N' in it.
SELECT
MYSCHEMA.ALL_TRUE_PKG.ALL_TRUE(YN)
FROM
MYSCHEMA.YN_TEST_TABLE
Finally, I'm not sure if this is relevant, but I'm using Toad 11.6.
Edit:
So I've tried inserting into a temp log table and that didn't work either.
I added the following
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT ALL_TRUE_T, value IN VARCHAR2)
RETURN NUMBER IS
BEGIN
BEGIN
INSERT INTO MYSCHEMA.LAWTONFOGLES_TEMP_LOG
(
ID,
Message,
Time
)
VALUES
(
'all_true',
'test1',
systimestamp
);
END;
IF value <> 'Y' OR self.TRUE_SO_FAR <> 'Y' THEN
self.TRUE_SO_FAR := 'N';
END IF;
RETURN ODCIConst.Success;
END;
There was nothing in the temp log, but also no error message. It is as if none of the 4 aggregate function parts are even being called.
EDIT2:
So, to make things more interesting, this works when it is not in a package.
I did the following
CREATE OR REPLACE FUNCTION MYSCHEMA.LAWTONFOGLES_ALL_TRUE (input VARCHAR2) RETURN VARCHAR2
AGGREGATE USING ALL_TRUE_T;
and then ran this
SELECT
MYSCHEMA.LAWTONFOGLES_ALL_TRUE(YN)
FROM
MYSCHEMA.YN_TEST_TABLE
and got the results I expected. It seems that the code itself isn't a problem, but putting it in a package causes it to break. Thursday my Oracle DBA will be opening a ticket up with oracle, so I'll be sure to update with why does putting this in a package break it but leaving it as just a function doesn't when they get back with us. Until then I may just have to keep this outside of a package.
Also, I tried to add a put_line on it when it was working and still did not get an output. I think that the way user defined aggregate functions work prevent put_line from working.
If you're using TOAD, be sure to turn on DBMS_OUTPUT recording before you run your proc so you can see your outputs. It should be on the bottom DBMS tab (if you have it open). Typically you'll see a red circle since it's defaulted as off. Click the circle so that it's green.
See this link as an example: http://geekbrigade.wordpress.com/2009/04/09/how-to-set-and-view-dbms-output-of-oralce-in-toad/

Oracle datapump exported tables

My situation is quite strange, and i don't have any ideea on how to handle it. Scenario:
In variable v_tables_param I have the following string (the names of the tables that iwant to export) 'IN(''REPORT_PERIOD'',''OBJECT_AVAILABILITY'')'.
when i try to specify the following metadata filter that i need in order export the tables :
DBMS_DATAPUMP.METADATA_FILTER(handle => n_h1, name =>'NAME_EXPR',value =>v_tables_param);
i get a ORA-39001: invalid argument value.
However, if i hrad code the exact value of v_tables_param into the metadata filter, it works like a charm :
DBMS_DATAPUMP.METADATA_FILTER(handle => n_h1, name =>'NAME_EXPR',value =>'IN(''REPORT_PERIOD'',''OBJECT_AVAILABILITY'')');
Any idea what is happening here?
Are there some weird scenarios in oracle when a hard coded string is different from a variable that has the same value ?
EDIT: I added the function that computes the value of v_tables_param
FUNCTION SPLIT_TABLES(
v_tables_list VARCHAR2 --this is a string that looks like "table1,table2,table3"
) RETURN VARCHAR2
IS
n_idx PLS_INTEGER;
n_i PLS_INTEGER := 0;
v_tables VARCHAR2(2000) := v_tables_list;
v_filter_value VARCHAR(2000);
v_current_table VARCHAR2(200);
BEGIN
v_filter_value := '''IN(';
LOOP
n_idx := instr(v_tables,',');
IF n_idx > 0 THEN
v_current_table := (substr(v_tables,1,n_idx-1));
v_filter_value := v_filter_value || '''''' || v_current_table || ''''',';
v_tables := substr(v_tables,n_idx+1);
n_i := n_i + 1;
ELSE
v_current_table := v_tables;
v_filter_value := v_filter_value || '''''' || v_current_table || ''''')''';
EXIT;
END IF;
END LOOP;
RETURN v_filter_value;
END SPLIT_TABLES;
Ther're actually more parameters to metadata_filter (nice example of a doc bug):
SQL> desc dbms_datapump.metadata_filter
Parameter Type Mode Default?
----------- -------- ---- --------
HANDLE NUMBER IN
NAME VARCHAR2 IN
VALUE VARCHAR2 IN
OBJECT_PATH VARCHAR2 IN Y
OBJECT_TYPE VARCHAR2 IN Y
HANDLE NUMBER IN
NAME VARCHAR2 IN
VALUE CLOB IN
OBJECT_PATH VARCHAR2 IN Y
OBJECT_TYPE VARCHAR2 IN Y
...and I believe you'll have to qualify the object type you're filtering for:
object_type => 'TABLE'
update after you provided the function source:
Remove two apostrophes from each side of the filter values.
Double apostrophes are required by the compiler only. The value of the filter parameter must contain single apostrophes, but your function creates them in pairs.
your variable should contain only single quote
variable = 'IN('REPORT_PERIOD','OBJECT_AVAILABILITY')'
then, pls try , it works

Resources