I have two tables with the same fields : vessel_details and vessel_history. There is a form provided to the user for the renewal of the vessel license. Upon page load, all the data of the vessel will be displayed(textbox) through the form. These data are retrieved from the vessel_details table. Once the user edited the details, and clicked the update button, the original details(before the editing) from the vessel_details should be transferred in the vessel_history table before the updating of the current filled-out/edited details in the vessel_details.
upon clicking the update button, how can i insert the original details from the table vessel_details to the other table (vessel_history),and eventually update the vessel_details table with the new (edited) details?
Without knowing what technique you are using to get you data, what you can do is clone original record container which might be a DTO or dataset or something else. Again you have to decide whether is deep clone or shadow clone and on update clone goes to history table and original updates values.
You could use a trigger in the database to do this. Then no matter what technology you use at the front end it will always work.
Related
I am populating 3 tables from my APEX application:
Customer
Order
CustomerOrder
First record is inserted into customer table, then order table and then a record created in CustomerOrder, linking the first two tables together.
Do there are 3 inserts, one after another
Insert into Customer …
If cust_id is not null then
Insert into Order..
If order_id is not null then
Insert into CustomerOrder
End If
End If
But what if issue occurs when the record is being inserted into CustomerOrder? The record in Order table will be left not linked to any customer, isolated.
Can this be prevented? Meaning if an error occurs anywhere in the code, can the whole thing be rolled back like with the transactions in SQL?
I wonder why you have CustomerOrder at all. Can an Order belong to more than one Customer? If not, it seems that you could simply have a Customer ID column in Order.
That aside, the answer to your question depends on how you have the application laid out. If you have one page where a user enters all the order information, including what customer the order belongs to; and that page calls a PL/SQL block that does multiple INSERTs; and you don't explicitly COMMIT within that PL/SQL block; then all of that takes place in a single transaction. Apex will commit that transaction if it completes without errors, or roll it back if not.
If you are splitting the data entry across multiple pages, then each page submit is going to be a separately committed transaction.
It makes sense to me that you would have a separate page for entering customer information. But I see no issue with committing the Customer record before entering the order information.
I wouldn't make sense to me to have one page to enter the order, and then another page to map the order to a customer. If you are selecting the customer on the order entry page, and inserted into Order and CustomerOrder in one PL/SQL block, then you should not have any orphaned orders.
Thanks in advance for your advice!
Background
I’m creating a database to track orders placed by customers.
An ‘Orders’ table stores general details about an order like the customer’s name, order date, and delivery-required date.
A separate ‘Order_Items’ table stores the specific items that the customer has ordered.
The is a one-to-many relationship between the ‘Orders’ table and ‘Order_Items’ table, i.e. one ‘Order’ can have many ‘Order_Items’, but each ‘Order_Item’ must be associated with only one ‘Order’.
Current State
Currently, I have a page where the user creates a new ‘Order’ record. The user is then taken to another page where they can create as many ‘Order_Item’ records as are needed for the order.
Desired State
What I would like to achieve is: When a user creates new ‘Order_Item’ records, it automatically allocates the current ‘Order’ record as the foreign key for the new ‘Order_Item’ record.
What I've Tried So Far
Manual Action By The User: One way of establishing the link between an 'Order' and all of its 'Order_Items' would be to add a drop-down widget which which effectively asks the user something like "Which order number do all of these items belong to"? The user's action would then establish the link between the two tables and associate one 'Order' with many 'Order_Items'. However, my goal is for this step to be handled programatically instead.
Official Documentation: I’ve referred to the offical documentation which was useful, but as I'm still learning I don’t really know exactly what to search for. The prefetch feature appeared promising but does not actually establish a link; it just loads associated records more efficiently.
App Maker Tutorials: I found an App Maker tutorial which creates an HR App where a user can create a list of ‘Departments’, then create a list of ‘Employees’, and then link an ‘Employee’ to a ‘Department’. However, in the example app this connection is established manually by the user. In my desired state I would like the link to be established programatically.
Manual Save Mode:
I’ve also tried switching to manual save mode so that the user has to create a draft ‘Orders’ record and then several draft ‘Order Items’ records and then save them all at once. However, I haven’t managed to make this work. I’m not sure whether the failure of this approach is because 1) I’m try to create draft records on more than one table, 2) I’m just not doing it correctly, or 3) I thought I read somewhere that draft records are deprecated.
Other Ideas
I'm very new to this field and am may be wrong, but I have a feeling I may need to use some scripting to establish the link. For example, maybe I could use a global variable to remember which 'Order' the user creates. Then, for each 'Order_Item' I could use the onBeforeCreate event to trigger a script that establishes the link between the 'Order_Item' and the 'Order' that was remembered from the previously established global variable.
Updated Question
Thanks Markus and Morfinismo for your answers. I have been using both answers with some success.
Morfinismo: I've successfully used the code you directed me to on existing records but cannot seem to get it to work for newly created records.
For example:
widget.datasource.createItem(); // This creates a new record
var managerRecord = app.datasources.Manager.item; // This sets the Manager of the currently selected parent record as a variable successfully.
var teamRecord = app.datasources.Teams.item; // This attempts to set the Manager of the currently selected record as a variable. However, the record that was created in line 1 is not selected. Therefore, App Maker does not seem to know which record this line of code relates to and returns the error Cannot set property ‘Manager’ of null.
// Assign the manager to the team.
teamRecord.Manager = managerRecord; // This successfully assigns the manager but only in cases where the previous line of code was successful (i.e. existing records and not newly created ones).
Do you have any suggestions or comments on how to apply this code to records that are created by the initial line of code in line 1?
I have found the easiest way to create related items for situations such as yours is to actually import a form with the datasource set to Parent: Child (relation) or Parent: Child (relation) (create). So in your case the datasource would need to be set to Order: Order_Items (relation).
You can get this accomplished in two different ways using the form widget wizard:
Option 1:
If your page datasource is set to Order_Items, drag your form on your page.
In the datasource selection section, your datasource in the form widget should default to `Inherited: Order_Items'. Click the 'Advanced' button in the bottom left corner, then from the datasources category find Order as your datasource, then select relations in the next field, and then Order_Items in the next field, choose 'Insert only' or 'Edit' form and then the appropriate fields you want in the form.
Now every item that gets created in that form will automatically be a child record of the currently selected record in your Order datasource.
Option 2:
If your page datasource is set to Order, drag your form on your page.
In the datasource selection section, your datasource in the form widget should default to Inherited: Order. Scroll down in your datasource selection section until you find Order: Order_Items (relation), then choose 'Insert only' or 'Edit' form and then the appropriate fields you want in the form.
Now every item that gets created in that form will automatically be a child record of the currently selected record in your Order datasource.
In your Order model, make sure that the security setting is set appropriately that a user is allowed to create relations of Order_Items in Order. That is the simplest approach in my opinion since you don't have to hard code the parent into your form or client/server scripts. It is automatically based on the currently selected parent, and is essentially doing the same thing that #Morfinismo explained in the client script section.
The comment I placed under your question included a link to the official documentation that explains what you need. Anyways, your question is not clear enough to determine whether you are creating the records via client script or server script, hence this is a very general answer.
To manage relations via client script:
var managerRecord = app.datasources.Manager.item;
var teamRecord = app.datasources.Teams.item;
// Assign the manager to the team.
teamRecord.Manager = managerRecord;
// Changes are saved automatically if the datasource in auto-save mode
// Add a team member to a Manager's team.
// Note: Retrieve Members on the client before proceeding, such as by using prefetch option in datasource - datasources Team -> Members)
var engineerRecord = app.datasources.TeamMember.item;
teamRecord.Members.push(engineerRecord);
To manage relations via server script:
// Get the record for the Team to modify.
var teamRecord = app.models.Teams.getRecord("team1");
// Assign a manager to the Team.
var managerRecord = app.models.EmployeeDB.getRecord("manager1");
teamRecord.Manager = managerRecord;
// Note: The new association is not saved yet
// Assign a team member to the Team.
var engineerRecord = app.models.EmployeeDB.getRecord("engineer1");
teamRecord.Members.push(engineerRecord);
// Save both changes to the database.
app.saveRecords([teamRecord]);
The above information is taken directly from the official documentation, which like I said, I referred to in the comment I placed under your question.
I have a SQL Server table that contains two columns AppID and GroupID. The table is populated from a asp listbox. An AppID can have many GroupID's associated with it.
It works fine for adding Groups for each App and when a user wants to edit a record I can populate the Listbox with the already selected items.
What I want to know is when a user edits the items in the listbox, they can deselect existing items and select new ones what is the best way to update the table in the database? Would I be better to delete all the records for the AppID or is there a better way?
There isnt likely to be more than 12 Groups linked to anyone App.
EDIT
Sorry should have said that the table is a link table between the Apps table and the Groups table. The IDs in the link table are the primary keys from those tables.
TIA
Pro grammatically it would be easier to delete everything for the AppID and add them all back in. However your performance would take a huge hit using this method.
So your best method from a performance perspective would be to split the operation into 2 parts:
find records in your link table that are no longer in your ListBox &
delete them
find records in your ListBox that aren't in the table & insert them
This will only work well if you keep track of the data to insert and delete as the user clicks on the ListBox. Then apply the changes all together as doing the inserts & deletes one record at a time would mean many more transactions which would be slower.
EDIT
A further performance improvement would be to turn some of the deletes & inserts into updates as updates are typically faster than delete + insert. Albeit this would add complexity to your code so it comes down to what is more important.
As before keep track of the deletes & inserts as the user makes changes to the ListBox
Count how many deletes & inserts you have
Take the lowest number and that is how many delete + inserts you can convert into an update. For example, if you need to delete GroupID 123 & insert GroupID 456, then instead just update GroupID 123 to 456.
If you have left over deletes, then perform those, otherwise handle the leftover inserts
I was wondering if there is any way to populate a table using two different records. My records have the same primary keys, but when I am adding the specific fields to my grid I have this error:
More than one data (key) in one scroll.
I tried to make a Control view field in my primary record, and then refer the new record fields as relative fields but in this case the data is not populating in my grid. Any help or hint will be much appreciated.
I've only done this where the 2nd record is a Derived/Work record.
Can you create a view that combines both records, and put the view in the grid? FYI, peoplesoft let's you update the data in a view, which is not typical in an oracle db system.
Ok guys finally after all discussion, and much try rounds I figured out how to do this.
You need to add a draw a grid beside your old grid and populate it with a new record, which has dynamic view (dynamic sql). The only important case there, is you need to make sure the order of your fields in your records, are in the same order of your fields in the SELECT statement of your sql. Otherwise you will see
an SQL error
.
Try to make a field as display control field which is acting as primary key for its native table and as Foreign key for some other record.. A field needs to be made related if is being fetched from some other record... that is from the record which is not under current consideration. I think this way one can fetch data into grid or scroll respectively from multiple records.
I have a column and I would like to edit some of its rows. The problem is that the table is a view so I cannot edit the rows. How would I proceed to solve this problem?
SQLite doesn't let you update views. But it does allow triggers on views. So you can write an INSTEAD OF UPDATE trigger that makes the appropriate modifications to the underlying table.
As dan04 pointed out, you can use triggers to update views (like in most other databases). For sqlite, see http://www.sqlite.org/lang_createtrigger.html#instead_of_trigger
Example with a view called "myview", containing a table "my_t2"
CREATE TRIGGER myview_update INSTEAD OF UPDATE ON myview
BEGIN
UPDATE my_t2 SET field1 = new.field1, field2 = new.field2 WHERE my_t2.key = old.key;
END
If it's a view, it's not a table. The data for the view is drawn from one or more other tables. Edit the underlying table and when you examine the data in the view it will reflect the changes you made.
A SQL View is a virtual table, which is based on SQL SELECT query. Essentially a view is very close to a real database table (it has columns and rows just like a regular table), except for the fact that the real tables store data, while the views don’t. The view’s data is generated dynamically when the view is referenced. A view references one or more existing database tables or other views. In effect every view is a filter of the table data referenced in it and this filter can restrict both the columns and the rows of the referenced tables.
If you wish to modify the data in your table, you cannot do so with a view. SQL Views are always read-only. If you want to modify your table outside of the View, then use something like an UPDATE or ALTER TABLE statement.