how display automated data on the display items in oracle forms - oracle10g

I have a code in the ADD Button , for displaying stored data(in the table) on the CONTROL Block
the below code is working fine but i am not getting serial_no on the Block
COMMIT_FORM;
Declare
Cursor Cur_BILL_DETAILS
Is Select code , item_name , qty , amount
From APPS.XXC_BILL_DETAILS
Where Bill_no = :bill_no;
Begin
Go_Block('CONTROL');
Open Cur_BILL_DETAILS;
Loop
Fetch Cur_BILL_DETAILS Into :CONTROL.CODE ,
:CONTROL.item_name ,
:CONTROL.qty ,
:CONTROL.amount;
Exit When Cur_BILL_DETAILS %Notfound;
Next_Record;
End Loop;
Close Cur_BILL_DETAILS;
First_Record;
End;
And i created the pre-insert on the CONTROL Block(non-database) as below for displaying Serial_no as
declare
v_no number;
Begin
select xxc_sno.nextval into v_no from dual;
:CONTROL.SNO:=v_no;
end;
Suppose ,
I am inserting into code, item_name,qty,amount and commited the record , the above ADD Button code worked fine.
The Pre-insert code not generating and displaying the no's as 1,2,3..
Ex:
Code item qty Amount
---- ---- --- -----
A AA 1 10
B BB 1 20
and click on the ADD Button, it is saved the inserted 2 records and goes the below(next , control block), display the Stored Records on the Control Block
Sno Code item qty Amount
---- ---- ---- --- -----
1 A AA 1 10
2 B BB 1 20
But the pre-insert trigger is not generating serial no's as 1,2 ,3 etc..(not effecting)
Can you please help me?
Thanks

Forms PRE-INSERT triggers fire during the posting of data to a base table block. A control block does not have a base table so PRE-INSERT will never fire. I am not sure (my Forms knowledge is rusty) but you may want to look at using a WHEN-NEW-RECORD-INSTANCE trigger instead.

Related

A bug in PostgreSQL suppress_redundant_updates_trigger?

I was working on a set of triggers in PostgreSQL and I think I stumbled on a bug on the built-in function/trigger suppress_redundant_updates_trigger(). It's fully reproducible on my configuration (PostgreSQL 12 on my laptop).
First I set up a table, with two "before each row" triggers:
CREATE TABLE test (id int, val text);
INSERT INTO test VALUES (1, 'one'), (2, 'two');
CREATE OR REPLACE FUNCTION am_i_touched() RETURNS trigger LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
RAISE NOTICE 'Yes, I am touched!';
RETURN NEW;
END;
$BODY$;
CREATE TRIGGER az_test_suppress_redundant_update
BEFORE UPDATE ON public.test
FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
-- Make sure trigger name is after the previous one
-- in alphabetical order as it drives execution order
CREATE TRIGGER bz_am_I_touched
BEFORE UPDATE ON public.test
FOR EACH ROW EXECUTE PROCEDURE am_i_touched();
I then run UPDATE test SET id = 1 WHERE id = 1. As expected, the update is suppressed by the first trigger since the row is left unchanged, and bz_am_i_touched() never fires. So far so good.
But then I run:
ALTER TABLE test ADD COLUMN newcol int
Now, I run again UPDATE test SET id = 1 WHERE id = 1... And this time, the update is NOT suppressed and bz_am_i_touched() fires! PGAdmin (v4) reports that one record was updated, not zero like the time before!
This is a one-off occurrence. Further UPDATE test SET id = 1 WHERE id = 1 work as expected... But then I tried UPDATE test SET id = 2 WHERE id = 2... and again I have this strange behavior - the update is not suppressed.
Is that an expected behavior? I can't understand how UPDATE test SET id = 1 WHERE id = 1 can result in the update not being suppressed.
The way the newcol NULL value is represented is different between the new tuple and the old tuple. So they are not considered to be the same, and so the update is not suppressed.
The tuples are compared in total with memcmp, so differences in even user-invisible bytes will be found significant. It doesn't loop through each field making individual type-dependent decisions about what differences are semantically meaningful. This seems to be intentional, for speed and simplicity. I doubt it would be considered a bug.

Create Trigger For Update another row automatically on same table using postgresql

I want to create a trigger that can update another row on the same table on PostgreSQL.
if i run the query like these:
UPDATE tokens
SET amount = (SELECT amount FROM tokens WHERE id = 1)
where id = 2
these result that i expected.
description:
i want to set field amount on a row with id:2, where the amount value is from query result on a subquery, so the amount value on id:2 is same with id:1
Hopefully, with this created trigger, i can do update amount value on id=1 so the amount value on id:2 is same with id:1
Before update result:
id | amount|
1 | 200 |
2 | 200 |
When i update the amount value on id:1 to 100 on, so the amount value on id:2 become 100
After update result:
id | amount|
1 | 100 |
2 | 100 |
Update for my temporary solution:
i just create the UDF like these
CREATE FUNCTION update_amount(id_ops integer, id_mir integer) returns boolean LANGUAGE plpgsql AS $$
BEGIN
UPDATE tokens SET amount = (SELECT amount FROM tokens WHERE id = id_ops) WHERE id = id_mir;
RETURN 1;
END;
$$;
description:
id_ops: id where the amount i always update
id_mir: id where the amount automatically update after i update the amount with id_ops
Example of using my written UDF to resolve my problem:
I update the amount of id: 1 to 2000. The amount of id: 2 not updated to 2000
When i run query select update_amount(1,2);
The amount of id: 2 will same with amount on id: 1
I Need a trigger on PostgreSQL to automate or replace the function of UDF that i wrote
What you want to do it not really that difficult, I'll show you. But first: This is a very very bad idea. In fact bad enough that some databases, most notable Oracle, throw an exception if try it. Unfortunately Postgres allows it. You essentially create a recursive update as you are updating the table that initiated the trigger. This update in turn initiates the trigger. Without logic to stop this recursion you could update every row in the table.
I assume this is an extract for a much larger requirement, or perhaps you just want to know how to create a trigger. So we begin:
-- setup
drop table if exists tokens;
create table tokens( id integer, amount numeric(6,2));
-- create initial test data
insert into tokens(id, amount)
values (1,100), (2,150.69), (3,95.50), (4,75), (5,16.40);
Now the heart Postgres trigger: the trigger function, and the trigger. Note the function must be defined prior to the trigger which calls it.
-- create a trigger function: That is a function returning trigger.
create or replace function tokens_bur_func()
returns trigger
language plpgsql
as $$
begin
if new.id = 1
then
update tokens
set amount = new.amount
where id = 2;
end if;
return new;
end ;
$$;
-- create the trigger
create trigger tokens_bur
before update of amount
on tokens
for each row execute procedure tokens_bur_func();
--- test
select *
from tokens
order by id;
-- do an initial update
update tokens
set amount = 200
where id = 1;
-- Query returned successfully: one row affected, 31 msec execution time.
-- 1 row? Yes: DML count does not see change made from within trigger.
-- but
select *
from tokens
order by id;
Hard coding ids in a trigger however is not very functional after all "update ... where id in (1,2)" would be much easier, and safer as it does not require the recursion stop logic. So a slightly more generic trigger function is:
-- More general but still vastly limited:
-- trigger that mirrors subsequent row whenever an odd id is updated.
create or replace function tokens_bur_func()
returns trigger
language plpgsql
as $$
begin
if mod(new.id, 2)=1
then
update tokens
set amount = new.amount
where id = new.id+1;
end if;
return new;
end ;
$$;
-- test
update tokens
set amount = 900
where id = 3;
update tokens
set amount = 18.95
where id in (2,5);
select *
from tokens
order by id;
No matter how you proceed you required prior knowledge of update specifics. For example you said "might be id 2 I can set mirror from id 3" to do so you would need to alter the database in some manner either changing the trigger function or the trigger to pass parameters. (Triggers can pass parameters but they are static, supplied at create trigger time).
Finally make sure you got your recursion stop logic down cold. Because if not:
-- The Danger: What happens WITHOUT the 'stopper condition'
-- Using an almost direct conversion of your UDT
-- using new_id as
create or replace function tokens_bur_func()
returns trigger
language plpgsql
as $$
begin
update tokens
set amount = new.amount
where id = new.id+1;
return new;
end ;
$$;
-- test
update tokens
set amount = 137.92
where id = 1;
-- Query returned successfully: one row affected, 31 msec execution time.
-- but
select *
from tokens
order by id;

Oracle Apex: radio buttons, forms and reports

Is it possible to create a radio button field or a checkbox field for each row of an interactive report?
If the above is possible, submit that selected row which would take the user to another report combining different tables?
Please explain how this is possible?
Many thanks
You can create items using apex_item if you want to create a check box you will need to use:
APEX_ITEM.CHECKBOX2( p_idx IN NUMBER
, p_value IN VARCHAR2 DEFAULT NULL
, p_attributes IN VARCHAR2 DEFAULT NULL
, p_checked_values IN VARCHAR2 DEFAULT NULL
, p_checked_values_delimiter IN VARCHAR2 DEFAULT ':'
, p_item_id IN VARCHAR2 DEFAULT NULL
, p_item_label IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2;
as you can see multiple examples in here if you want an IR with a custom checkbox you can do it this way:
SELECT APEX_ITEM.CHECKBOX2(1,empno) "Select"
, ename
, job
FROM emp
ORDER by 1
If I understand correctly after the user select any number of check boxes he can click on a button to show another report where you will need the selected check boxes. One way to achieve this is:
Create a process to add the selected check boxes to a collection
BEGIN
apex_collection.create_or_truncate_collection(p_collection_name => 'col_tmp');
FOR I in 1..APEX_APPLICATION.G_F01.COUNT
LOOP
apex_collection.add_member( p_collection_name => 'col_tmp'
, p_c001 => APEX_APPLICATION.G_F01(i));
END LOOP;
END;
Create a branch to the page with the other report. In this page you can use the collection in your select in order to show the right information:
SELECT e.ename
, e.job
, d.dname
FROM EMP e,
DEPT d
WHERE e.deptno = d.deptno
AND empno IN (SELECT C001
FROM apex_collections
WHERE collection_name = 'COL_TMP')
NOTE: In the select you must use the collection name in upper case.

inserting the data through the loop

I have a table like below:
business
id name address
-----------------
1
2
.
.
.
100
This table contains 100 records...
Now i am inserting the business table records to business_extra table using loop
target table like below:
business_extra
id name address
-------------------
create or replace function() returns text as
$$
begin
for i in(select * from business)
loop
insert into business_extra values(i.id,i.name,i.address);
end loop;
end;
$language plpgsql
here exactly what i want means
In this loop i took first row and then it will insert the row into business_extra
table...up to 100th row complete then only it will insert.
but i dont want that if i fetch 1st record then it will insert data in business_extra
using loop
It is totally unnecessary to use a PL/PgSQL function and a loop here. It's also very inefficient. Do it with plain SQL:
INSERT INTO business_data (id, name, address)
SELECT i.id, i.name, i.address
FROM business i
ORDER BY i.id
LIMIT 100;
as an example. I'm guessing about what you mean by "until 100", and guessing that you want the first 100 businesses as sorted by id.
Your original function is probably wrong, since it can take any 100 businesses in some random order. SELECT results have no order unless you specifically specify one.
but i dont want that if i fetch 1st record then it will insert data in business_extra
I have no idea what you are trying to say with this part.

trigger compilation error(insert)

this is my code:
create or replace trigger th
after insert on stock
for each row
declare
sqty number;
rl number;
isb number;
rq number;
begin
set sqty=(select stockqty from inserted);
set rl=(select reorderlevel from inserted);
set isb=(select isbn from inserted);
set rq=(select reorderquantity from inserted);
go
if sqty> rl then
delete from stock where isb=isbn;
insert into stock values(isb,sqty,rl,rq);
end if;
end;
questions:
1.if a after insert trigger is used it means all this happens after inserting right?what if i want to not insert a particular data what do i do?i mean like if weight<15 dont insert like that.
2.if i have inserted multiple data how to retrieve them?does a trigger get called for each of the insert?(if its an insert trigger).
3.this is giving me a compilation error,i just am not able to find the mistake,even using a cursor is giving me an error.
create or replace trigger t1
after insert on stock for each row
declare
cursor cl is select isbn,stockqty,reorderlevel,reorderquantity from stock where isbn>0;
begin
for c2 in c1 loop
if c2.stockqty>c2.reorderlevel then
delete from stock where isbn=c2.isbn;
insert into stock values(c2.isbn,c2.reorderquantity,c2.reorderlevel,c2.reorderquantity);
end if;
end loop;
end;
Btw i am using sql developer,weidly many of my trigger are not executing,but they are executing in oracle 8i.
I can't figure out what you are trying to do, but your syntax is all wrong (where did you get it from? SQL Server?). See documentation for the correct syntax.
You wrote:
set sqty=(select stockqty from inserted);
I suspect you want to do this:
sqty := :new.stockqty;
Ditto the next 3 lines.
Then you have:
go
which is nonsense. Just remove it.
Then you have:
if sqty> rl then
delete from stock where isb=isbn;
insert into stock values(isb,sqty,rl,rq);
end if;
Which appears to mean that if the inserted row's stockqty exceeds its reorderlevel then delete it and then insert it right back in again. This makes no sense, and cannot be done using a FOR EACH ROW trigger as you will get the "table is mutating" error.
Please explain what you are trying to achieve and then we can help see if it can be achieved.
Answers:
1. You can use a Check Constraint for that
2. I don't understand what you mean:
if you want to find duplicated records then you can group by all fields and use
having count(*) >0
but why use a trigger ?
or maybe you mean that you want the values within the trigger ? if so, use
:new and :old