Fetch only Number from the value Oracle Apex - oracle

I need to fetch only number from the item how to perform that.
For Ex: P2510_PAYMENT_TOTAL = 208.00 Dr
I need to fetch only 208 from the above item how to get it
I am trying to create DA to show error if P2510_SUMMARY_OS_DR <=P2510_PAYMENT_TOTAL
My Dynamic action code
:P2510_PLSQL_ERROR_MESSAGE := NULL;
IF ROUND(:P2510_SUMMARY_OS_DR,2) <= :P2510_PAYMENT_TOTAL THEN
:P2510_PLSQL_ERROR_MESSAGE :=
'It looks like the values you''ve entered don''t match.'
||' The value of the Match value must match the value of Outstanding.'
||' Please try again.';
END IF;
But this DA is not working i am getting "PL/SQL: numeric or value error: character to number conversion error"

If item value is 208.00 Dr, then you can't round it ("Dr" isn't numeric, it raises the error).
Try
if to_number(substr(:P2510_SUMMARY_OS_DR, 1, instr(:P2510_SUMMARY_OS_DR, ' ') - 1)) <=
to_number(:P2510_PAYMENT_TOTAL)
then
...

Related

My Trigger getting looping and Case Error when i try to join two tables on it

I have 2 tables, Contract and Bankslip.
I need to get the date field from the Contract table, and set the date on Bankslip table, but it's getting in a loop, I think!
How can i do it?
Here is my code:
create or replace TRIGGER GFLANCAM_ATUALIZA_DATA_EMISSAO
BEFORE INSERT ON GFLANCAM
FOR EACH ROW
DECLARE
DATA_INICIO_CONTRATO DATE;
BEGIN
CASE WHEN :NEW.DOCUMENTO <> ' ' then
SELECT dt_inicio
INTO DATA_INICIO_CONTRATO
from ctcontra
where cd_contrato = :NEW.documento;
:NEW.data := DATA_INICIO_CONTRATO;
END CASE;
END;
What am I doing wrong?
Much of the trigger is unnecessary.
You can accomplish your goal without the CASE and without defining a variable.
CREATE OR REPLACE TRIGGER GFLANCAM_ATUALIZA_DATA_EMISSAO
BEFORE INSERT
ON GFLANCAM
FOR EACH ROW
BEGIN
-- Consider following:
-- IF NVL (:NEW.DOCUMENTO, ' ') <> ' '
IF :NEW.DOCUMENTO <> ' '
THEN
-- Following line may cause ORA-01403: no data found
SELECT dt_inicio INTO :NEW.data FROM ctcontra WHERE cd_contrato = :NEW.documento;
END IF;
END;
/
A few notes:
If you want to catch NULL values then add the NVL shown above.
Watch out for the case where a corresponding record is not found in ctcontra--this condition would result in ORA-01403: no data found (which might be exactly what you want in this case).
Make sure that ctcontra has only one record for each cd_contrato value, otherwise you will get a ORA-01422: exact fetch returns more than requested number of rows.
Take a look at the update:
{CREATE OR REPLACE TRIGGER GFLANCAM_ATUALIZA_DATA_EMISSAO
AFTER INSERT ON GFLANCAM
FOR EACH ROW
DECLARE
DATA_INICIO_CONTRATO DATE;
BEGIN
IF DOCUMENTO <> ' ' THEN
SELECT dt_inicio INTO DATA_INICIO_CONTRATO from ctcontra where cd_contrato =
DOCUMENTO;
UPDATE GFLANCAM SET DATA = DATA_INICIO_CONTRATO;
END IF;
END;}

Oracle SQL Create Trigger to insert SEQ.nextval

I am creating a trigger to add same SEQ.nextval numbers to two fields such as follows:
SITE_NUM SITE_NUM_COPY Site_Name
346 346 XYZ
347 347 ABC
348 348 DEF
Whenever a new row is added through an application I want the SITE_NUM and SITE_NUM_COPY will be auto generated through the trigger.
This is what I have put together:
create or replace trigger SITE_TRIGGER
before insert or update on STRATEGY_SITES for each row
begin
if updating then
if :new.SITE_NUM is null and :new.SITE_NUM_Copy is NULL then
:new.SITE_NUM := :old.SITE_NUM
and :old.SITE_NUM := :new.SITE_NUM_COPY;
end if;
end if;
if inserting then
:new.SITE_NUM := SITENUM_SEQ.nextval
and :new.SITE_NUM_COPY := SITENUM_SEQ.nextval;
end if;
end;
Getting the following error:
Error(7,31): PLS-00103: Encountered the symbol "=" when expecting one of the following:
. ( * # % & = - + ; < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like like2 like4 likec between || indicator multiset member submultiset
The symbol "* was inserted before "=" to continue.
The error is not very helpful but is stemming from you using and to, apparently, seperate two statements inside each if block. The statement terminator/separator is a semicolon.
It looks like you are trying to do this for the first one:
if updating then
if :new.SITE_NUM is null and :new.SITE_NUM_Copy is NULL then
:new.SITE_NUM := :old.SITE_NUM;
:old.SITE_NUM := :new.SITE_NUM_COPY; -- illegal
end if;
end if;
but you cannot change the :old values; it isn't clear what you expect to happen, ot least as the value assigning must be null. You may just want to remove that line.
And for the second part:
if inserting then
:new.SITE_NUM := SITENUM_SEQ.nextval;
:new.SITE_NUM_COPY := SITENUM_SEQ.currval;
end if;
I've changed the second assignment to use currval because you said you wanted the same value for both columns. If you call nextval for both assignments they will get different values simce the sequnce will increment twice.

How to stop repeating values/ Null values from being output in a PL/SQL loop

I'm having an issue where null values and repeating columns are being output in my stored procedure.
Currently, an array is being passed into my procedure as TYPE. I need to output all part numbers/pdc/src from the array. Currently if the records in TYPE (array) match what's in inventory there are no issues. If they don't exist then only nulls will be output for those respective columns in the cursor.
I've tried inserting the current record in a variable and using a NVL operator but then the records just end up repeating. Does anyone have any suggestions?
PROCEDURE iws_update (i_Tbulk_type IN update_bulk_type,
o_Cresultset OUT SYS_REFCURSOR)
AS
partcount VARCHAR2 (20) := NULL;
sumcount VARCHAR2 (4) := NULL;
miscount VARCHAR2 (1) := NULL;
BEGIN
FOR i IN i_Tbulk_type.FIRST .. i_Tbulk_type.LAST
LOOP
partcount := i_Tbulk_type (i).part_no; --
sumcount := i_Tbulk_type (i).pdc;
miscount := i_Tbulk_type (i).part_no;
UPDATE inventory i -- update logic
SET i.diff_qty = i_Tbulk_type (i).mismatch_qty,
i.aval_qty = ( (i.aval_qty + i.diff_qty) - i_Tbulk_type (i).mismatch_qty)
WHERE i.dept_cd = i_Tbulk_type (i).pdc --First PK validation
AND i.src = i_Tbulk_type (i).src --second PK validation
AND TRIM (i.part_no) = TRIM (i_Tbulk_type (i).part_no) -- third PK validation
AND i.diff_qty >= 0 -- second step in validation: diff qty must be greater than zero
AND ( (i.diff_qty + i.aval_qty) - i_Tbulk_type (i).mismatch_qty) >=
0 ; -- Final condition that must be met: the sum of diff and aval quantity minus the qty passed in by the array must be greater than or equal to zero. If all conditions are met update proceeds.
COMMIT;
OPEN o_Cresultset FOR --cursor to send back records and flags to Back End
SELECT t.pdc, -- array dept code
t.src, -- array source
t.part_no, -- array part no
CASE WHEN i.part_no IS NULL THEN 'FAIL' ELSE 'PASS' END AS part_no_flag, -- if part no is null then it doesn't exist in inventory table and will print 'FAIL' as a flag. else pass.
( (i.diff_qty + i.aval_qty) - t.mismatch_qty) AS avail_qty,-- sends the quantity based on second validation method. line 440. If output is negative BE will mark as fail
i.diff_qty AS unmatch_qty -- prints qty. if negative BE marks as fail.
FROM TABLE (CAST (i_Tbulk_type AS update_bulk_type)) t
LEFT JOIN inventory i
ON i.dept_cd = t.pdc
AND i.src = t.src
AND TRIM (i.part_no) = TRIM (t.part_no);
END LOOP;
END iws_update;

Why I receive "NO DATA FOUND" exception when I use RETURNING clause after update statement?

I'm coding a simple LOOP FOR to update a column from a table using information populated in an associative array. All seems right when I only use UPDATE statement but when I add a RETURNING clause I receive "NO DATA FOUND" error. Thanks!
DECLARE
TYPE emps_info IS TABLE OF employees23%ROWTYPE
INDEX BY PLS_INTEGER;
t_emps_current_info emps_info;
t_emps_new_info emps_info;
BEGIN
SELECT *
BULK COLLECT INTO t_emps_current_info
FROM employees;
FOR emps_index IN t_emps_current_info.FIRST .. t_emps_current_info.LAST
LOOP
IF
NVL(t_emps_current_info(emps_index).commission_pct, 0) = 0 THEN
UPDATE employees23
SET commission_pct = 0.3
WHERE employee_id = t_emps_current_info(emps_index).employee_id;
ELSIF
t_emps_current_info(emps_index).commission_pct BETWEEN 0.1 AND 0.3 THEN
UPDATE employees23
SET commission_pct = 0.5
WHERE employee_id = t_emps_current_info(emps_index).employee_id;
END IF;
END LOOP;
END;
Now When I add RETURNING clause I receive following error:
DECLARE
TYPE emps_info IS TABLE OF employees23%ROWTYPE
INDEX BY PLS_INTEGER;
t_emps_current_info emps_info;
t_emps_new_info emps_info;
BEGIN
SELECT *
BULK COLLECT INTO t_emps_current_info
FROM employees;
FOR emps_index IN t_emps_current_info.FIRST .. t_emps_current_info.LAST
LOOP
IF
NVL(t_emps_current_info(emps_index).commission_pct, 0) = 0 THEN
UPDATE employees23
SET commission_pct = 0.3
WHERE employee_id = t_emps_current_info(emps_index).employee_id
RETURNING commission_pct
INTO t_emps_new_info(emps_index).commission_pct;
ELSIF
t_emps_current_info(emps_index).commission_pct BETWEEN 0.1 AND 0.3 THEN
UPDATE employees23
SET commission_pct = 0.5
WHERE employee_id = t_emps_current_info(emps_index).employee_id
RETURNING commission_pct
INTO t_emps_new_info(emps_index).commission_pct;
END IF;
DBMS_OUTPUT.PUT_LINE('EMPLOYEE_ID: ' ||
t_emps_current_info(emps_index).employee_id ||
' OLD COMMISSION: ' ||
NVL(t_emps_current_info(emps_index).commission_pct, 0)
|| ' NEW COMMISSION: ' ||
t_emps_new_info(emps_index).commission_pct);
END LOOP;
END;
Informe de error -
ORA-01403: no data found
ORA-06512: at line 22
01403. 00000 - "no data found"
*Cause: No data was found from the objects.
*Action: There was no data from the objects which may be due to end of fetch.
This part in your code
DBMS_OUTPUT.PUT_LINE('EMPLOYEE_ID: ' ||
t_emps_current_info(emps_index).employee_id ||
' OLD COMMISSION: ' ||
NVL(t_emps_current_info(emps_index).commission_pct, 0)
|| ' NEW COMMISSION: ' ||
t_emps_new_info(emps_index).commission_pct);
prints both the original array as well as the returning array .
At some point of time during your update it may happen that your update statement doesnt update any row , in that case your original array will have a value at that index , but your returning array wont
So check for the existence of index to avoid this error
case when t_emps_new_info.exists(emps_index) then
dbms_output.put_line('print something') ;
else dbms_output.put_line('print something else') ;
end case;
You are getting NO_DATA_FOUND because nowhere in your code are you initialising (creating) the t_emps_new_info(emps_index) records - whenever your code tries to assign t_emps_new_info(emps_index).commission_pct it will fail.
I'm not sure why it should be necessary, but I would change each UPDATE statement return the value into a simple local variable. Then I'd set the table record field to the simple variable.
Probably unrelated, but I noticed that your ELSIF test isn't doing an NVL() on the existing t_emps_current_info(emps_index).commission_pct, as your IF test does.
If it was me, I'd log the updates of both sides of the IF-ELSEIF to see if one update is working while the other fails. Maybe it's just failing on the ELSIF, because of the missing NVL()?

Error PLS-00103 while compiling a function

I get this error when I compile my function.
PLS-00103: Encountered the symbol "*" when expecting one of the following:
:= . ( # % ;
Here is the code:
CREATE OR REPLACE FUNCTION IncreaseSalary
(para_empid IN employee.employeeid%TYPE, para_increase IN NUMBER)
RETURN NUMBER
IS
v_SalaryOut NUMBER(10,2);
v_salary2 NUMBER;
BEGIN
SELECT Salary INTO v_Salary2
FROM Employee
WHERE employeeid = para_empid;
--this is the area that pertains to the error
(v_salary2 * para_increase) + v_salary2 = v_salaryout;
RETURN v_SalaryOut;
EXCEPTION
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Employee not found.');
END IncreaseSalary;
/
This next part wouldn't be part of the function and is not part of the error
but probably has errors.
DECLARE
v_SalaryOutput NUMBER := IncreaseSalary;
BEGIN
IncreaseSalary('01885', '20%');
DBMS_OUTPUT.PUT_LINE ('Increased Salary: ')
|| TO_CHAR(v_SalaryOutput));
END;
/
The point is to take in two numbers (employeeid and the percentage to increase whatever salary is already listed in the table) and return the updated salary. I don't understand why I can't multiply.
You cannot assign value to variable like that. The target variable should come first. It should be,
v_salaryout := (v_salary2 * para_increase) + v_salary2;
You have declared para_increase as NUMBER. But while calling the function, you are passing '20%' as the value. This will result in numeric or value error: character to number conversion error.
There is an extra bracket in you dbms_output statement.
DBMS_OUTPUT.PUT_LINE ('Increased Salary: ' || TO_CHAR(v_SalaryOutput));

Resources