Can anybody suggest a good trigger that I can use in a text box. The operation that i intend to use in the text box is when the user changes the value in the text box, I call a Procedure that updates that value in the Database table with a commit. However ,so the moment the user changes the value and presses enter it should go to the next item, before which it updates the DB. It works fine in the KEY-NEXT-ITEM trigger. However, one problem is that say the user changes the value in the fld , but does not press tab or enter, but directly F10 to commit. My trigger in the text box(i.e KEY-NEXT-ITEM) does not fire. I tried a POST-TEXT-ITEM , but it does not let me use the ,COMMIT or NEXT_ITEM built ins. I want the trigger to fire the moment the user exits the item and also it should go to the next item in the form
Use WHEN-VALIDATE-ITEM trigger. This trigger is basically intended to validate value entered by user. It fires every time when forms decided, that user finished field value - when user leaves field, when user presses commit, etc.
Unfortunately you are not able to use COMMIT_FORM in this trigger. Forms recommend make direct database changes in transactional triggers only. To implement database change with commit, make your database procedure running in autonomous transaction:
CREATE OR REPLACE PROCEDURE do_somethning (some_id NUMBER, some_value VARCHAR2) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE some_table SET some_column = some_value
WHERE table_id = some_id;
COMMIT;
END do_somethning;
Yout WHEN-VALIDATE-ITEM trigger can be like this
BEGIN
-- probably do some validations
...
-- call your procedure
do_something(:some_block.id, :some_block.your_field);
END;
Related
In a summary: I edited a database item, ON-LOCK trigger fired, and then executed:
set_record_property(get_block_property('my_block', current_record),'my_block',status, QUERY_STATUS);
And after that whenever I edit any database item in that record or even programmatically call LOCK_RECORD, the ON-LOCK trigger is not firing.
Why am I even doing this, is another story, but is there some other place (record property) where Forms store info that "this record has already been locked"?
There is no way that Forms check something in the database, because in my ON-LOCK trigger I have left just a debug message.
ON-LOCK trigger should have the select '1' into dummy from yourTable where record_key = xxx for update nowait; statement. Check if you have that.
When user begin filling the record then they click other record before committing i want to clear the last record like it never filled.
So i create when-validate-record in data block as below:
begin
if :MYBLOCK.SEQ is null then --if there is no seq yet, means its not committed
Clear_Record;
end if;
end;
But clear_record causes error that says Invalid limited CLEAR_RECORD procedure and usage seems correct to me. And i also tried Clear_Record(no_validate) but it also doesn't work. I saw some usage of clear_record and i can't get why it doesn't work. I could use some help.
Thanks in advance.
Restricted procedures (not limited, as you put it) can't be called from all triggers; WHEN-VALIDATE-RECORD being one of them.
One option you might choose is to interact with the user and tell them what to do. Still the WHEN-VALIDATE-RECORD trigger:
if :MYBLOCK.SEQ is null then -- if there is no seq yet, means its not committed
message('Save the record or - if you do not need it - delete it');
raise form_trigger_failure;
end if;
Benefit of such an approach is that user (not the procedure in background) decides what to do. I wouldn't want to enter 20 fields on the screen, accidentally click one of previous records and lose everything I've done so far.
what I wanted is to update my table using values from a multi record block and here is what I tried in post forms commit:
BEGIN
FIRST_RECORD;
LOOP
UPDATE table1
SET ord_no = :blk.new_val;
EXIT WHEN :SYSTEM.LAST_RECORD='TRUE';
NEXT_RECORD;
END LOOP;
END;
but when I save I got an error
FRM-40737: Illegal restricted procedure
FIRST-RECORD in POST-FORMS-COMMIT trigger.
OK, a few things to talk about here
1) I'm assuming that 'table1' is NOT the table on which the block is based. If the block was based on table1, simply as the user edits entries on screen, then when you do a COMMIT_FORM command (or the users clicks Save) then the appropriate updates will be done for you automatically. (That is the main use of a database-table based block).
2) So I'm assuming that 'table1' is something OTHER than the block based table. The next thing is that you probably need a WHERE clause on your update statement. I assume that you are updating a particular in table1 based on a particular value from the block? So it would be something like:
update table1
set ord_no = :blk.new_val
where keycol = :blk.some_key_val
3) You cannot perform certain navigation style operations when in the middle of a commit, hence the error. A workaround for this is to defer the operation until the completion of the navigation via a timer. So your code is something like:
Declare
l_timer timer;
Begin
l_timer := find_timer('DEFERRED_CHANGES');
if not id_null(l_timer) then
Delete_Timer(l_timer);
end if;
l_timer := Create_Timer('DEFERRED_CHANGES', 100, no_Repeat);
End;
That creates a timer that will fire once 100ms after your trigger completes (choose name, and time accordingly) and then you have your original code on a when-time-expired trigger.
But please - check out my point (1) first.
I'm trying to create my trigger but it's asking for binds EVERY time. It works the way I want it to when I click apply on the window that appears... However, it will log an error...
My trigger checks to see if a client is active or not and do NOT allow changes if it is found to be active...
CREATE Trigger Client_Activity
BEFORE Insert or Update or Delete ON Client
FOR EACH ROW
DECLARE
VAR_AC char(2);
BEGIN
IF UPDATING THEN
SELECT Activity INTO VAR_AC
FROM Client_Additionals
WHERE Activity = :Old.Activity;
IF Activity = 'AC'
THEN Raise_Application_Error(-20999, 'active')
END IF;
END;
/
ORACLE VERSION 12 USING SQLDEVELOPER
You have two syntax errors in your trigger:
The IF is missing an END IF
You need to compare the content of the variable var_ac
You are missing a ; after the Raise_Application_Error()
Putting that together, you can create the trigger without problems.
However, you need to use the "Run Script" button in SQL Developer to run a PL/SQL block like that.
SQL*Plus requires no special handling:
I googled this but, unfortunately, could not find any solution.
I have a simple form (Oracle Forms Builder 10g) with a single block. The form is written in Oracle EBS style, that is, the block is based on a view that fetches the base table fields together with the rowid and DML events (on-insert, on-update etc. triggers) are handled by a table handler package.
The functionality I wanted to add was the following: when a user creates a new record, the form automatically suggests values for all fields in the form. So, I created a WHEN-CREATE-RECORD trigger that calculates the field values and assigns them. All, except the primary key wich is based on a Sequence and is handled by the package.
Everything runs OK when I create the new record but when I attempt to save it, all I get is a FRM-40401 "no changes to save" error and nothing happens.
I tried to trace the error and it seems like the form considers the record as NEW with no changes on it. This happens even if I try to explicitly alter the record status to INSERT.
I already tried to change the default behaviour to STANDARD.COMMIT (created an ON-COMMIT trigger for that) but this did not dfix anything.
For the record, I tried to make the form table-based, getting rid of table handlers and leaving all DML to Forms. I still get FRM-40401.
I can't understand what is going wrong, any ideas please?
The record status is reset to NEW after the when-create-record trigger completes. This normally makes sense, since you are effectively setting the default values for items, but the user hasn't actually entered any data yet.
You need something to mark the record for insert after the trigger has finished - normally the user would do this when they enter some data into the record. If you want the user to be able to save the record without changing anything in it, you could perhaps add something to the save button to do a no-change assignment, e.g.
:MYBLOCK.ANYITEM := :MYBLOCK.ANYITEM;
This would cause the record to be marked for insert.
OK, for the time being I used the classic TIMER workaround and everything works as it should:
PACKAGE body form_timers IS
PROCEDURE CREATE_NEW_RECORD;
procedure do_create(name varchar2) is
timer_id TIMER;
Begin
timer_id := CREATE_TIMER(name,1,NO_REPEAT);
End;
procedure expired is
expired_timer CHAR(20);
BEGIN
expired_timer:=GET_APPLICATION_PROPERTY(TIMER_NAME);
IF expired_timer='CREATE_NEW_RECORD' THEN
CREATE_NEW_RECORD;
-- ELSIF expired_timer='T2' THEN
-- /* handle timer T2 */ NULL;
ELSE
NULL;
END IF;
END;
PROCEDURE CREATE_NEW_RECORD IS
/* create record logic goes here */
END;
END;
... but still, I'd like to know why this behaviour occurs.