How to get the values of a checkbox in after trigger in PL/SQL? - sql

I have a form for creating new events in Oracle Apex. With that form I am able to create new events just fine. But at the bottom of that form is a checkbox where the user will specify the clubs that are involved in organizing the event.
The list of values for the checkbox which you can see at the bottom of the image above is set to a sql query which selects 'club_name' and 'club_id' from 'club' table.
Now what i want to do is after the events gets successfully created, the club_id of the checked clubs with the id of the newly created event needs to be inserted into the 'club_event' junction table which related each event with their organizing club. So for that I thought of creating after trigger on events table. But I couldn't find how can I access the id's of the club selected in the plsql code. So my question is how my I do so and is my approach for relating event with organizing club fine? Thank you.
With the suggestiong from "Koen" I tried to I tries to implement it through "Process". But I am having problem in making my script work.
DECLARE
type idarray IS VARRAY(10) OF VARCHAR2(10);
ids idarray;
BEGIN
ids := apex_string.split(:P72_CLUBS, ':');
FOR id IN ids LOOP
INSERT INTO club_event
VALUES(id, P72_EVENT_ID);
END LOOP;
END;
What are the things that I am doing wrong and how may I resolve it?

You don't need a trigger for that. Use a page process instead. The values of the page item (I assume that is P1_CLUB) will be passed on page submit as a colon separated list of return values (in your case club_id). Use apex_string.split to convert the colon separated list to a pl/sql array . Loop through the array and insert/update/delete the records in/from the clubs table .

In addition to Koen's answer, if you want to view the event and also want to populate the checkbox with the checked values, you will have to set the following attributes for the checkbox page item:
Source - Type = SQL Query (return colon separated value)
SQL Query = select club_id from my_club_to_event_table where event_id = :P1_EVENT_ID
Used = Always, replacing any existing value in session state
Assuming P1_EVENT_ID is the primary key page item on that page.

Related

How to update records form a from whose data source is set to view in Oracle Apex?

My oracle apex application has an events page that has a v_event view as its data source. This view contains all the column that an event table contains plus it also has club_name column that holds the name of the organizing club. The report displays correctly as I want it for now.
When I try to update a record I get an error saying 'data manipulation operation not legal on this view'
This must be because the data source for the page is a view. How can I solve this problem ?
Also when I try to create new events I get an error:
First I thought that the '... non key-preserved table' occurred because the relationship between event and club_event(junction table between club and event) table was one to many and same event row was repeating multiple times if there were multiple clubs organizing it. So to solve this issue I "LISTAGG" clause to combine multiple club names for a single event in a single row using comma separation as you can see in the second row of the first image above. But it didn't solve the issue. What am I doing wrong?
By the way the entire page is a "report with form" that oracle apex provides. So I am able solve this problem by create a new page and setting its data source to event table. But I just wanted to learn if there is a way that I can create a new event through the view table.
Also one final question. How can I map the values in 'From College' and 'From Community' column in the first image to be "yes" if the value in the table is 1 and "no" is the value is 0 ?
Thank you.
As far as I remember, there are several tables involved here. Even if it weren't for Apex, the answer is to create an instead of trigger which fires when view is updated, and then trigger body decides which tables are updated and how.
In Apex, you could - additionally - try to write your own processes that handle inserts, updates and deletes. In other words, don't use automatic row processing as it won't work, but create your processes.
As of mapping 1/0 to "yes/no":
in (interactive) report, use CASE (or DECODE)
in form, either create radio button or select list item
The view needs to have a 1:1 mapping to the table and the column that has the "LISTAGG" should have the attribute "Source > Query Only" set to "On".

Cursor returns Multiple Rows & Columns

My SQL is limited and I have inherited the schema so please go easy!
The upper tables are populated, the lower section is to be completed.
The customer wants a simple reference, C_SCAFFOLD_DOMAIN_COMBO, for every C_SEQUENCE_RESULT of the same TYPE having the same C_PROTEIN_REGIONs (only ever two) of the same REGION_NAME.
My intention is to read each C_SEQUENCE_RESULT getting the (2) C_PROTEIN_REGION.SEQUENCEs with their REGION_NAME using a cursor.
I can then check if they are referenced by a C_SCAFFOLD_DOMAIN_COMBO already.
If so, then simply add the correct C_SCAFFOLD_DOMAIN_NAME FK to C_SEQUENCE_RESULT.
If not, create a new C_SCAFFOLD_DOMAIN_NAME entry with the appropriate C_PROTEIN_REGION refs and add the FK to C_SEQUENCE_RESULT.
My SQL query returns two results for each C_SEQUENCE_RESULT e.g.
REGION_NAME------SEQUENCE
Loop 1------ABCDEFG
Loop 2------HIJKLMN
Running as a simple query and can INSERT INTO a temp table and get the values. As a cursor I don’t seem to be able.
How can I read the data returned above using a cursor?
Thanks

Dynamic query creation

I have a scenario wherein with the following details:
I have a form that contains fields like firstname,middle name,lastname,dob,pin,address for Client 1.
Now this form has to cater more than one client . The problem statement is - different clients may require different number of fields to be displayed on front end. For eg: a 2nd client would want - Country field instead of pin, would not require address on the form.
Now when i submit the form , currently i have a constant query which takes values of - firstname,middle name,lastname,dob,pin,address and inserts it into database for Client 1. I want to develop a query in a way that it is created at runtime and inserts only the values that come from the form into the database..
I hope my problem is clear. Can anyone help?????????????
You need to think about why you are doing this.
It will get hideously complex with just person form, add in more and it will balloon big style.
Dynamically building queries isn't particularly complicated, but it's a lot of code to do it.
Just think about each field you want to add to the query and it's type. What if a property on your person record was an image of them.
Do you have a configuration of the form, is the promary key on the record an auto inc, is it a compound key, do you use defaults, are some fields not null. How are you going to bubble back referential integrity exceptions...
Do the all singing all dancing version and basically you reinvent something like the Access IDE....
Personally I'd have a Person object with a set of Person Properties, they would have name, a value and a boolean to say whether they'd been changed.
Once you have teh list of chnaged properties and beacseu you are in the Person object you know the table is persons, it's keyed by an autoinc bigint, gender is mandatory and defaults to Male...
You have a fighting chance.
Your query should use parameters
So it would be say Insert Persons(FirstName, LastName, PIN) Values(#FirstName,#LastName,#PIN)
Then you'd nip through your changed fields and add parameters with same name, type and value.
As I said you can really go to town with this one, may be it's time for a night in though.
This should mean that some fields in your table like address and pin can be empty, in that case you can do without a dynamic query. Just collect all the inputs from your form and insert them into your table. Those form fields that were left empty due to different user needs will consequently have their corresponding field in your table empty. So just list all the needed fields in your table and all the possible input from your form in your insertion query.

XForms: Delete trigger in table row (repeat)

I am using an XForms' repeat to build up a table (very similar to http://wiki.orbeon.com/forms/doc/developer-guide/xforms-repeat). Each row should get a delete trigger to remove it. The following code does only delete the selected item, is it somehow possible to use the current repeat index as a value for at?
<xforms:delete nodeset="employees" at="index('employee-repeat')"/>
Thank you for your help!
If you have a delete trigger for every row, then you don't need to use the index() function. Instead, just refer to the current node, as in:
<xforms:repeat nodeset="employees">
...
<xforms:trigger>
<xforms:label>Delete</xforms:label>
<xforms:delete ev:event="DOMActivate" nodeset="."/>
</xforms:trigger>
</xforms:repeat>
If you had just one trigger for the whole repeat (i.e. at the beginning and/or end of the table listing the employees), then you could use index() to refer to the "current" employee. That means that users would first need to click somewhere on that employee to make it the current one, and then click on the button. This is a somewhat unusual web UI, and so I would rather have one delete button per employee or use checkboxes for users to select which employees they want to act on.

How can I bind a multi-row update or insert statement to a form?

I have a table Prices:
ID -- primary key, autonumber long integer
PriceDate -- Date
Price - Currency
Quantity - Number, DECIMAL subtype
UnitPrice - Number, DECIMAL subtype (an update statement is run to keep this in synch with price and quantity, but it's just a convenience for indexing... probably it'll be replaced with an expression in my queries)
ItemNote - Text
NewStores_ID - long integer key, lookup to another table of stores
NewItems_ID - long integer key, lookup to another table of items
To enter prices for a given store on a given day, I would like to be able to select the store and date ONCE on a form, then enter the items individually in a datasheet. For reasons unexplained, this proves difficult.
I can create a subform binding everything but the store and price to a temp table TempPrices with the same structure as the original. Then I run the SQL statement
INSERT INTO Prices
(PriceDate,Price,Quantity,UnitPrice,Brand,ItemNote,NewStores_ID,NewItems_ID)
SELECT
PriceDate,Price,Quantity,Price/Quantity AS
UnitPrice,Brand,ItemNote,NewStores_ID,NewItems_ID)
FROM Temp_Prices;
This will feed all the new rows into the main table. But, when I want to set the store and date only once, I run into problems. I've tried using named parameters for date an store in the insert statement... which can cause a pop-up prompt, but I cannot bind it to a form control. I've tried binding an update statement for those fields in the temp table to a form... but it doesn't even show an option to bind a multi-row update.
How can I get this to work with a minimum of clumsy hackery? It seems like there ought to be a simple solution, and if I were using something like PHP or JDBC I'd just run an extra query.
Edit: changed storage type for Quantity and UnitPrice to Number, Decimal subtype in place of double float. Just so people won't cry about using a float in any proximity to currency. It doesn't pose a problem in my use, but there are enough people who have a knee-jerk reaction to that.
Edit 2: Form/Subform
I'm trying to structure this as a master form with a either fields for entering store name and date, or a subform for the same, then a subform mapping to the temporary table for entering pricing data. There is an action button to run the insert/update queries to dump the temp table into my main prices table and clear out the temp table. However, the problem is that I can't figure out how to get the date/store fields in the master (or subform) to bind to an insert/update value applied to all the new rows at once.
Edit 3: SQL Statements (for clarity)
INSERT INTO
PRICES(NewStores_ID,PriceDate,NewItems_ID,Brand,Price,Quantity,
UnitPrice,ItemNote)
SELECT
#MyStore_ID,#MyPriceDate,NewItems_ID,Brand,Price,Quantity,
Price/Quantity,ItemNote
FROM TempPrices;
UPDATE TempPrices SET PriceDate=#MyPriceDate,NewStores_ID=#MyStoreID;
For these queries, I cannot bind parameters for #MyStore_ID or #MyPriceDate to fields in any form. The queries don't show up as options when trying to link them to a form. I can run them and get popup boxes to input parameters, but that's not what I want.
This is the target I'm aiming at:
"I would like to be able to select the store and date ONCE on a form, then enter the items individually in a datasheet."
However, if you have a reason why you need to do it with a temp table and DML statements, then this suggestion will not be useful.
I created a Prices table with only 4 fields, then a query on that table which I used as the Record Source for a form, "fsubPrices":
SELECT p.ID, p.NewStores_ID, p.PriceDate, p.Price
FROM Prices AS p
ORDER BY p.NewStores_ID, p.PriceDate;
The form has text boxes (txtNewStores_ID, txtPriceDate, and txtPrice) bound to the similarly-named query fields. I set Enabled=Yes for txtPrice, and Enabled=No for the other two.
Then I created an unbound form "frmPrices", and in the form header added a combo box "cboStores" and a text box "txtPriceDate". The combo has Bound Column = 1 with this query for its Row Source:
SELECT l.Store_ID, l.Store_name FROM tblkupStores AS l ORDER BY l.Store_name;
Then I added fsubPrices as a subform control to the detail section of frmPrices. The tricky part is setting the Link Master/Child Fields. There is a "wizardy dialog thing", but it will only allow you to select from the available fields, and I needed to link controls on the main form with fields on the subform. To do that, I had to type what I wanted directly into the subform control's property sheet:
Link Child Fields......NewStores_ID;PriceDate
Link Master Fields.....cboStores;txtPriceDate
The result is ... choose a store and date combination in the main form ... any matching records are displayed in the subform. You can navigate to the "new record" in the subform to add records for that store/date combination. But the txtNewStores_ID and txtPriceDate controls don't show the updated values until the new record is saved.
I hope this is close to what you want. It's actually fairly quick and easy to create; not so easy to describe.
You can't really do that. You are always going to have one row being worked with at a time.
What you can do is simulate it by changing the form's Default View from "Single Form" to "Continuous Form" or perhaps "Data sheet" and making is a child(sub) form of a master form.
Then you can put the store and date on the Master form, and linking to the child form using the NewStores_ID and PriceDate fields.